Aug 20, 2012

เขียน Loop ยังไงดี?

ในการเขียนโปรแกรม เรามักต้องพบปะกับท่านี้เสมอๆ
text = input()
while text != 'exit':
    # do something with text
    # ...
    text = input()
ดูเผินๆ ก็ไม่น่ามีปัญหาอะไร แต่นี่จะทำให้โปรแกรมเมอร์สำคัญผิดกับ input ครั้งแรก หรือไม่งั้นก็มองโค้ดผ่านๆ แล้วนึกว่า input ด้านนอกนั้นจะไม่เกี่ยวกับกิจกรรมที่เกิดขึ้นใน while loop ที่ตามมาเลย (ยิ่งถ้าต้องมีการ pre-process input ก่อนที่จะเอาไป check while อีก) ทางแก้ง่ายๆ คือเปลี่ยนไปเขียนแบบนี้แทน
while True:
    text = input()
    if text == 'exit':
        break
    # do something with text
    # ...


อีกเรื่องที่ไม่ค่อยเกี่ยวกันเท่าไหร่คือ การรับข้อมูลจาก database มาแสดงผล ส่วนใหญ่จะทำท่านี้
$result = mysql_query($sql);
while ($row = mysql_fetch_row($result)) {
    echo $row[0], $row[1], $row[2];
}
ในทางปฎิบัติมันก็ใช้ได้เลย แต่ถ้ามาคิดๆ ดูแล้ว ข้อมูลที่ query ออกมาจาก database ได้นั้นควรจะมีจำนวนจำกัดเสมอ (ไม่มี database ไหนที่เก็บข้อมูลได้เป็น infinity เป็นแน่??) นั่นหมายความว่าทางทฤษฎีแล้ว มันไม่ควรเขียนด้วย while loop แต่ควรเขียนด้วย for loop (อาจเป็น for-each loop) เช่นนี้
// codeigniter active record
$query = $this->db->get($sql);
foreach ($query->result() as $row) {
    echo $row->title, $row->author, $row->content;
}
ท่านี้จะทำให้มีปัญหาด้าน memory (เพราะต้อง query ข้อมูลทั้งหมดออกมาเก็บไว้ใน array ก่อน แล้วจึงค่อยวนเข้าไปอ่านข้อมูลใน array นั้น) ซึ่งแก้ได้ที่ระดับ library โดยเปลี่ยนไปใช้ generator แทน array



ท้ายสุด กลับไปที่ while loop แบบแรก โดยมีเงื่อนไขเพิ่มเติมตรงที่อยากรู้ว่าเป็นการทำงานรอบที่เท่าไหร่ อาจเขียนเพิ่มเป็น
i = 0
while True:
    text = input()
    if text == 'exit':
        break
    # do something with text
    # ...
    print('loop no:', i, '; input is:', text)
    i += 1
จะเห็นว่ามี i = 0 เป็น initial statement อยู่นอก scope ของ while ตรงนี้จริงๆ ไม่มีปัญหาอะไรเลย แต่ถ้าอยากให้มันสวยขึ้นด้วยการจัดระเบียบ block สามารถใช้ประโยชน์ของ infinity generator ได้
from itertools import count

for i in count():
    text = input()
    if text == 'exit':
        break
    # do something with text
    # ...
    print('loop no:', i, '; input is:', text)
หรือยิ่งไปกว่านั้น ทำการเปลี่ยนรูปแบบการเขียนเพื่อให้ไม่ต้องตรวจสอบสำหรับ break ออกจาก loop แต่ไปตรวจตั้งแต่หัว loop เลยว่าหลุดออกจาก loop นี้หรือยัง อย่างนี้
from itertools import count

for i, text in zip(count(), iter(input, 'exit')):
    # do something with text
    # ...
    print('loop no:', i, '; input is:', text)
แนวคิดจะเปลี่ยนไปนิดนึงด้วย ตรงที่เราไม่ได้ใช้ while loop แล้ว (loop แต่ละครั้งไม่เชื่อมโยงกัน) เปลี่ยนมาเป็น for loop (แต่ละครั้งมีความเกี่ยวเนื่องกัน อย่างน้อยๆ ก็ index ที่ไล่กันไปเรื่อยๆ) นั่นเอง ซึ่งส่วนตัวแล้วผมชอบอย่างหลังมากกว่า

Aug 19, 2012

จัดระเบียบ Blog



สืบเนื่องจากเมื่อวานอ่าน blog ของ @phatpeth แล้วรู้สึกว่า theme มันสวยดี ... อันที่จริงเราเองก็ไปเล่นตั้งแต่วันแรกๆ ที่มันออกเลยนะ แต่ทีนี้มันติดปัญหาที่ว่า syntax highlighter ตัวเก่งของเราเนี่ย มันดันทำงานไม่ได้ในโหมดนี้ซะหนิ (กลัวว่าต้องไปใช้วิธี cap code เป็นภาพเอาเหมือนของ @iMacbaszii) เลยอู้ไว้ก่อน ไม่ยอมย้ายมาใช้แบบนี้ซักที

บังเอิญว่าวันนี้คิดไงไม่รู้ (ว่างจัด?) ตอนแรกว่าจะย้ายทั้ง blog ของเราไปอยู่บน GitHub Pages แล้ว เพราะถูกโฉลกกับ markdown มากๆ แต่ลองได้แป๊ปๆ รู้สึก learning curve มันสูงเกินไป อีกทั้งพวก comment เก่าๆ ก็ไม่น่าจะย้ายตามมาได้ด้วย

ตัดใจได้ก็เปลี่ยนมานั่งหาวิธี hack เอา syntax highlighter ใช้กับเจ้า blogger จนได้ (จริงๆ เปลี่ยนค่ายไปใช้ prettifier แหละ) ก็ต้องขอขอบคุณ Alex Conrad ผู้เขียน bootstrap-lib อันนี้ไว้ให้ด้วยเน้อ ;)

ตอนนี้ก็ติดอยู่อย่างเดียวตรงที่พื้นหลังของแต่ละ post มันเปลี่ยนเป็นสีเข้มๆ ไม่ได้ --- แต่ก็ช่างมันเหอะ จะได้ออกจากโลกมืดๆ ซะบ้าง หลังจากใช้สีดำเป็น default มาตั้งแต่ปี 5 ปีก่อน (ก่อนหน้านั้นอีกตอนอยู่ที่ spaces.live.com ใช้สีขาวนะเออ) ก็หวังว่าจะอ่าน blog กันได้สบายตาขึ้นนะครับ TwT

เสียดายอย่างสองอย่างตรงที่ theme dynamic view นี่มันแสดง facebook like box ไม่ได้แล้ว พวก feed aggregator ก็เอามาแปะข้างๆ ไม่ได้ (งานนี้ tutuor0x อดอัพตาม เพราะมีสัญญาผูกพันกับ blognone อยู่ว่าต้องแสดง feed แลกกัน) ก็น่าเสียดายเล็กน้อยเหมือนกันแต่ไม่เป็นไร

อ๋อ นอกจากเปลี่ยน theme แล้ว ยังจัดระเบียบ tag ใหม่ด้วย คือเมื่อก่อนเนี่ยใช้ระบบ category มาตลอด ซึ่งก็เข้าท่าดีเพราะสมัยนั้นเขียนเป็นหัวข้อๆ ไป แต่พักหลังนี้รู้สึกว่าเขียนกระจัดกระจายมากเลย คิดว่าเปลี่ยนมาใช้ tag น่าจะ work กว่านะ

ที่เหลือก็คงต้องหาภาพมาประกอบบทความแต่ละตอนบ้างแล้วสินะ ไม่งั้นเวลาดูแบบ flipcard แล้วจะรู้สึกโล้นๆ 555

Aug 18, 2012

ทำไม Functional Programming ถึงไม่ได้รับความนิยม


จากที่ @lewcpe คอมเมนท์ไว้ในตอนก่อน มานั่งคิดๆ ดูว่าทำไม functional programming ถึงไม่ได้รับความนิยมเท่าไหร่

คิดว่าสาเหตุใหญ่ๆ น่าจะเป็นเพราะปรกติแล้ว มนุษย์เราจะคิดการทำงานทาง "ซ้าย -> ขวา" คิดจากส่วนที่เล็กสุดออกไปยังระดับที่ใหญ่ขึ้นเรื่อยๆ เช่นเขียนโปรแกรมอย่างนี้

sh:
echo 'hello to the old world' | tr ' ' '\n' | sort -r | paste -sd ' '
ruby:
puts 'hello to the old world'.split.sort.reverse.join ' '
แต่ในการเขียนโปรแกรมแบบ functional programming การทำงานของจะเป็นในทิศทาง "ซ้าย <- ขวา" แทน ซึ่งขัดกับความรู้สึกของเรา

python:
print(' '.join(reversed(sorted('hello to the old world'.split()))))
haskell:
print (join " " . reverse . sort . splitOn " ") "hello to the old world"


อีกเรื่องที่ยากคงเป็นเพราะไม่มี for/while loop มีแต่ recursion ให้ใช้ อันนี้สาย imperative ทำใจลำบากพอควรเลย

ส่วนเรื่องอื่นๆ อย่าง immutable คงไม่มีปัญหาเท่าไหร่ อันที่จริงถ้าไม่สนว่าจะ optimize กันสุดๆ ไม่ว่าจะเขียนด้วยภาษาอะไรก็ควรยึดเรื่องนี้ไว้หน่อย มันทำให้ bug งี่เง่าหายไปได้หลายตัวเลยหละ :3

Aug 17, 2012

Function Composition กับ Programming


ตอนม.ปลาย คงเคยเห็นฟังก์ชั่นที่เขียนแทนด้วยสัญลักษณ์ g o f กันมาแล้ว ซึ่งมันหมายความง่ายๆ เช่นนี้
(g o f) (x) = g(f(x))
(นิยามเต็มๆ ของมันคือ ถ้า f: X -> Y และ g: Y -> Z แล้ว g o f: X -> Z ---- ที่ต้องนิยามเช่นนี้เพราะเราจะสามารถละการเขียน argument x ติดไปกับนิยามได้)

ในการเขียนโปรแกรม (โดยเฉพาะเชิง functional) เรามักต้องทำงานแบบฟังก์ชันต่อเนื่อง คือ output จาก function หนึ่ง จะถูกนำมาใช้เป็น input ให้ฟังก์ชันถัดไปเป็นลูกโซ่

เขียนอธิบายเป็นภาษาโปรแกรมได้คือ
first_input = x
first_output = f(first_input)
second_input = first_output
second_output = g(second_input)
y = second_output
หรือเพื่อไม่ให้เปลืองตัวแปร ทั้งหมดนี้สามารถย่อได้เหลือ
y = g(f(x))
คำถามคือ ถ้าเราต้องการประกาศแค่ฟังก์ชั่นที่ทำงานต่อกันไปเรื่อยๆ เช่นนี้ โดยที่ไม่ต้องการใส่ input ให้ฟังก์ชั่นโดยทันที เราจะทำอย่างไร?

ทางออกหนึ่งคือใช้ lambda เข้าช่วย
h = lambda x: g(f(x))
แล้วเวลาจะเรียกใช้ฟังก์ชั่นนี้ ก็แค่สั่ง
y = h(x)
ฟังดูง่ายดี แต่นึกดูอีกที ทำไมเราถึงต้องทำอะไรให้มันยุ่งยากด้วยการเอา lambda เข้ามาเกี่ยวด้วย?

ในภาษา imperative คงไม่มีทางเลือกอื่น แต่สำหรับภาษา functional จ๋าอย่าง Haskell เราสามารถเขียนแบบนี้ได้
let h = g . f
จะเห็นว่าง่ายดายเหมือนกับ g o f ตอนแรกเลย เวลาใช้ก็แค่
h x
หรือถ้าจะละการประกาศฟังก์ชั่น h ทิ้งไป เพื่อหาผลลัพท์ทันทีเลย ก็ทำได้โดย
(g . f) x
อ่าห์... นี่มันคณิตศาสตร์ชัดๆ!!

Aug 16, 2012

ความเคยชิน


คิดมานานแล้วว่านิ้วก้อยซ้ายมันใช้งานน้อยมากๆ และปุ่ม CapsLock ก็ไม่โดนใช้เลย น่าจะเอาปุ่มนี้ไว้ใช้เปลี่ยนภาษา

เดิมเคยเปลี่ยนภาษาด้วย ~ (Thai-Windows style) มาก่อน ต่อมาใช้ Linux ที่ต้องใช้ปุ่ม ~ บ่อยๆ เลยเปลี่ยนเป็น Alt+Shift ซึ่งมันจะมีปัญหา lost focus บ้าง คราวนีเปลี่ยนอีกรอบ เลยจับเวลาที่ต้องใช้ปรับตัวซักหน่อย (เช่นเดียวกับที่เคยทำตอนเปลี่ยนจาก Emacs มาเป็น vi [1] [2])

ปรากฏว่าใช้เวลาแค่วันเดียวเท่านั้นเองแฮะ น่าแปลกใจมากๆ

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

สรุปว่าอย่าไปใจร้อนสินะ เวลาจะเปลี่ยนอะไรซักอย่าง (แต่ก็อย่าเอื่อยเฉื่อย เฉไฉไม่ยอมเปลี่ยนพอ)

Jul 10, 2012

ความประทับใจกับห้องสมุดวิทย์ฯ มช.

ตอนไปยืมวันแรกๆ ที่เปิดเทอม ก็บอกว่ายังไม่ได้จ่ายตังค์ค่าเทอม ยังยืมไม่ได้ ... เอ่อ พี่ครับ ที่นี่เค้าเปิดเทอมก่อน จ่ายตังค์สัปดาห์ที่สองโว้ย ให้รอสัปดาห์หน้าลูกเดียวเลยหรือไงวะ

สัปดาห์ถัดมา จ่ายตังค์ค่าเทอมเรียบร้อยหนังสือที่จะยืมตั้งแต่คราวแรกแม่งหายอีก ไม่มีระบบจองหนังสือหรือไงวะ

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

เอาใหม่ อีกวันนึงเอาใบเสร็จค่าเทอมไปยืมจนสำเร็จ ระหว่างนั้นก็ไปออกบัตรนศ.ใหม่ด้วย เพราะใบเก่าหมดอายุ

... ผ่านไปสองอาทิตย์อ่านหนังสือจบ เอาไปคืน เห็นเล่มที่จะยืมตั้งแต่คราวแรกพอดี เลยหยิบไปเคาน์เตอร์ แม่ง บอกบัตรนศ.กูเป็นบัตรใหม่ บัตรมันไม่ link กับบัตรเก่า ยืมไม่ได้ ต้องไป activate บัตรที่สำนักทะเบียนก่อน

ห่าเอ้ย หมดความอดทนแล้วโว้ย

Jul 8, 2012

ข้าวมันไก่?

สั่งหมีขาวน้ำตก... บอกว่าร้าน "ไม่น่า" จะมี เอาเป็นเย็นตาโฟแทนมั้ย (ตรูไม่กินเย็นตาโฟเว้ย เอาแบบธรรมดามาไม่ได้เหรอ -- ว่าแต่ร้านก๋วยเตี๋ยวที่ไหนบ้าง ที่ไม่มีน้ำตกเนี่ย)

เอาใหม่ สั่งข้าวมันไก่ทอด... ได้ข้าวมันไก่ต้ม (ทั้งๆ ที่คราวนี้ร้านมันแขวนไก่ทอดไว้ข้างๆ กันเลย) - -"

ก็พอเข้าใจแล้วหละ ว่าทำไมตัวเองถึงติดคำว่า "อะไรก็ได้" ไปเสียหมด

ไม่ใช่ไม่อยากคิด (โว้ย) แต่พอคิดทีไร แม่ง "ไม่เคย" ได้อย่างคิดเลย

เอ่อ ไม่คิดดีกว่าหวะ

One More Time, One More Chance



วันนี้หยิบเอา 5cm ฉบับการ์ตูนที่เพิ่งออกมาอ่าน พบว่า part 1 เนือยๆ ทำบรรยากาศได้ดีเหมือนกับในหนัง คือก็ไม่น่าเบื่อซะทีเดียว แต่ก็เหมือนว่าตอนนี้ไม่มีจุด peak เอาซะงั้น (มันหลบหายไปพร้อมกับการแสดงออกของตัวเอกนั่นแหละ)

อ่านจบ part 1 จะวางละ ง่วงนอน+ดูจากความหนาแล้ว part 2 ไม่น่าจะเล่าจบได้ในเล่มนี้... แล้วเล่มต่อไปจะออกเมื่อไหร่ก็ไม่รู้ กลัวลงแดงตายซะก่อน...

แต่จนแล้วจนรอด ก็หยิบ part 2 มาอ่านต่อจนได้ ซึ่งต้องยอมรับว่า ประหลาดใจ (แบบไม่ประหลาดใจ) พอสมควร เพราะเนื้อเรื่องเล่าไว้ละเอียดกว่าในหนังมากๆ (ก็ไม่น่าแปลก part 1 ในหนังได้เวลาไปตั้งครึ่งนึงเลย part 2, 3 ก็โดนตัดฉับๆๆ ซะ)

อ่านจบเล่ม (แต่ไม่จบ part) ทนไม่ไหว มาเปิดอ่านภาษาอังกฤษในเน็ตต่อซะ เลยเข้าใจเรื่องราวขึ้นอีกเยอะเลย

และเสียน้ำตาอีกตามเคย TwT

ไปๆ มาๆ รู้ตัวอีกทีก็นั่งดู MV ตัวข้างบนอีกแล้ว...

รถไฟที่วิ่งคั่นกลางระหว่างคนสองคนนั้น ก็ยังคงเป็นฉากที่ทำให้ใจจะขาดเหมือนเช่นทุกที

... แต่จริงๆ แล้วนะ การดับความหวังไปซะเลย ก็ยังดีกว่าปล่อยให้หวังลมแล้งๆ แทบไม่มีทางเป็นจริงสินะ

สุดท้ายก็ได้แต่กลับมาถามตัวเองอีกครั้งว่า ถึงเวลาที่จะก้าวเดินต่อไปหรือยัง?



ปล. อันข้างล่างนี่ สำหรับใครที่อยากให้จบแบบ happy ending นะ :')

Jun 13, 2012

อยากทำ อย่างที่ 5 โปรแกรมแก้ไขเอกสารที่มองภาพรวมเป็นต้นไม้

วันนี้เห็น @awkwin ทวีตเกี่ยวกับความ *** สุดจะบรรยายของ JavaScript เลยได้ฤกษ์ขุดกระทู้ในตำนานมาอ่านอีกรอบ แล้วก็ได้สัมผัสถึงความ !@#$%^&* ของภาษา APL ซึ่งคอมเมนท์ในนั้นบอกไว้ว่า มันคงเป็นภาษาที่เจ๋งและกี๊คมากเลยถ้าอยู่ในหนัง ก็เลยทำให้นึกถึงหนังเรื่อง Stealth ตอนที่ศูนย์คอมเข้าไปดูโค้ดของโปรแกรมเพื่อหาบั๊ก (ส่วนนี้ในหนังกากมาก เพราะแม่งเล่นง่าย เอาโค้ดส่วนที่เป็นบั๊กไปไว้ "ระหว่างบรรทัด" เลย ซึ่งในความเป็นจริงโค้ดมันจะซ้อนอยู่ตรงนั้นได้ยังไงวะ) ถึงตอนนี้ก็ฉุกคิดได้ว่า เอ่อ ไม่เห็นจะเจ๋งตรงไหนเลย ถ้ามันแต่งมาเวอร์ๆ แต่ไม่มีทางเป็นไปได้ในโลกความเป็นจริง ...

... แล้วก็มาคิดได้ว่า อึม หรือโปรแกรมแก้เอกสารในหนังนั้นมันเป็นแบบโคตรล้ำยุคหว่า สามารถแสดงข้อความซ้อนๆ กันแบบ 3 มิติได้ เลยนั่งคิดต่ออีกซักพักนึงแล้วพบว่าโคตรไร้สาระ โค้ดที่เขียนกันอยู่ 2 มิติจะไปแสดงผลแบบ 3 มิติให้งง+เก็บบั๊กยากขึ้นทำไมหละ

ถอยกลับมา 1 ก้าว.. เอ่อ แต่ถ้าได้เขียนโค้ดแบบ 3 มิติจริงๆ คงเจ๋งไม่น้อยเลยนะ ก็เลยลองออกแบบว่า ไอ้การเขียนโค้ด 3 มิติ (ถ้ามันจะมีจริง) มันควรจะเป็นยังไงกันนะ?

คิดไปเรื่อยๆ โดยอิงจากตัวอย่างในปัจจุบัน ก็พบว่ารูปแบบโค้ดโดยทั่วไปจะออกแนวๆ นี้



ซึ่งถ้ามองในมุมของโปรแกรมเมอร์ที่เชี่ยวแล้วคงไม่มีปัญหา (เริ่มอ่านโปรแกรมจาก main ด้านล่างสุด แล้วโดดไปดูคลาส/ฟังก์ชันแค่เวลาที่ต้องการข้อมูลเพิ่มเติม)

แต่สำหรับโปรแกรมเมอร์มือใหม่ (อย่างผม) นี่ทำให้เกิดปัญหาที่เรียกว่า "เริ่มไม่ถูก" ขั้นรุนแรง ตั้งแต่เริ่มไม่ถูกว่าจะดูโค้ดที่ไหนก่อนดี? ทำไมต้องมองโปรแกรมตามแบบที่คอมพิวเตอร์ทำงานโดยการเริ่มจาก import requirement/dependency ต่างๆ ให้ครบก่อนแล้วจึงจะเริ่ม main ได้? ทิศทางการเขียนโปรแกรมควรจะเขียนแบบ top-down หรือ bottom-up กันแน่?

เลยได้ข้อสรุปสำหรับตัวเองว่า มันคงจะเหมาะกว่า ถ้าเริ่มมาก็สามารถเขียน concept ทั้งหมดของ main ได้เลย อยากใช้ฟังก์ชันใหม่ชื่ออะไรก็เขียนๆ ไปก่อน พอวางโครงเสร็จก็ค่อยกลับมาดูว่ามีฟังก์ชันไหนที่ยังไม่ได้เขียนกฎให้มัน ซึ่งพอดับเบิลคลิกที่ชื่อฟังก์ชันนั้นๆ ก็จะเป็นการเปิดป๊อปอัพหน้าต่างใหม่สำหรับเขียนกฎให้มันนั่นเอง (ยืมแนวคิดมาจาก lambda)



โดยรวมแล้วก็คงคล้ายๆ กับ Inspect Element ของเว็บเบราว์เซอร์ คือเริ่มดูจาก root node ไล่ลงไปเรื่อยๆ นั่นเอง เพียงแต่เปลี่ยนการ expand tag ไปเป็นการเปิดหน้าต่างใหม่แทน

รายละเอียดปลีกย่อย (ถ้าจะทำจริงๆ) ก็คงต้อง highlight สีของฟังก์ชันที่ยังไม่ได้เขียนกฎให้เด่นหน่อย ส่วนถ้าฟังก์ชันไหนเขียนไปแล้วแต่ติดแท๊ก FIXME หรือ TODO ไว้ ก็เปลี่ยนไป highlight ด้วยอีกสีหนึ่ง (จะได้รู้ว่ามีข้อผิดพลาดที่ฟังก์ชันนี้ และกลับมาแก้ไขทีหลังได้ง่าย) แล้วก็คงต้องดักพวก recursion ด้วย ส่วนการเขียนเพิ่มฟังก์ชันใหม่ๆ เข้าไป ต้องเอามันไปแทรกไว้ก่อน main เสมอ

คิดออกแค่นี้ ง่วงแล้ว ลองนอนดูก่อนว่าจะหายบ้ามั้ย 555

Jun 2, 2012

Opensource ไม่ใช่ของฟรี, คนทำไม่ได้อิ่มทิพย์

เรื่องหนึ่งที่เข้าใจผิดๆ กันมากเกี่ยวกับวงการไอที คือความคิดที่ว่า opensource คือของฟรี การนำ opensource มาใช้งานมีค่าใช้จ่ายเป็นศูนย์

อันที่จริงก็มีหลายคนเขียนถึงเรื่องนี้ไว้หลายครั้งแล้ว: 0, 1, 2 (ฯลฯ ที่ผมไม่สามารถหาเจอได้แล้ว) ซึ่งตอนนั้นผมเองอ่านบทความเหล่านั้นก็ยังไม่ค่อยเข้าใจเท่าไหร่ จนกระทั่งมาได้ทำงานกับ opensource จริงจัง

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

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

จาก 2 เคสที่ยกมานี้ จะเห็นว่าตัว opensource ไม่ได้จ่ายเงินให้นักพัฒนาเลย แต่เป็นผู้ว่าจ้างนั่นเองที่จ่ายเงินให้นักพัฒนาโดยตรง และโปรเจค opensource ก็โตได้เพราะเงินในส่วนนี้

ใช่ครับ opensource ไม่ใช่ของฟรี และคนทำก็ไม่ได้อิ่มทิพย์!!