Category Archives: Uncategorized

เชื่อมต่อ Clojure REPL เข้าไปที่ VM ที่ทำงานอยู่

คนที่เขียน Java มาอาจจะเคยต้อง restart server เป็น debug mode เพื่อต่อ debugger ของ IDE เข้าไป debug ปัญหา โดยมีความยุ่งยากคือต้อง restart ซึ่งอาจจะรบกวนการใช้งานของ user หรือบางครั้งหลังจาก restart แล้วปัญหาก็ดันหายไป

คนที่เขียน Ruby มาอาจจะเคย start irb บน server เพื่อลองรันคำสั่งต่างๆ แต่มันก็เป็นคนละโปรเซสกับที่ server ทำงานอยู่

บน Clojure เราสามารถเปิด port เอาไว้เชื่อมต่อ repl เข้าไปที่ VM หรือ server ที่ทำงานอยู่ได้ง่ายๆ โดยใช้ฟีเจอร์ที่ชื่อว่า Socket Server ซึ่งถูกเพิ่มเข้ามาใน Clojure เวอร์ชั่น 1.8

การใช้งานทำได้โดยการเพิ่ม option นี้เข้าไปเวลา start JVM

-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"

* :accept คือ ฟังก์ชันที่จะถูกเรียกเมื่อมีการติดต่อเข้ามาทาง socket

ในที่นี้ผมขอยกตัวอย่างรัน repl ปกติขึ้นมาหนึ่ง vm พร้อมเปิด socket ให้เชื่อมต่อ repl เข้ามาเพิ่มได้อีกละกัน

ปกติผมจะ start repl ด้วยคำสั่งนี้

$ rlwrap java -jar /path/to/clojure.jar

เราก็ทำการเพิ่ม option ข้างต้นเข้าไป

$ rlwrap java -Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" -jar /path/to/clojure.jar

เมื่อทำการรันคำสั่งด้านบนนี้ repl จะถูก start ขึ้นมาปกติ เมื่อ start เสร็จแล้ว เราสามารถ connect เข้าไปที่ VM นั้นผ่าน socket ได้โดยใช้ telnet ดังนี้

$ telnet localhost 5555

เราก็จะได้ repl ขึ้นมาอีกอันซึ่ง share data และ memory เดียวกับ repl แรกทั้งหมด เราสามารถทำทุกอย่างได้ตามชอบใจกับ VM นั้น

รายละเอียดเพิ่มเติมที่ Launching a Socket Server

เขียนครั้งแรกที่ https://www.facebook.com/groups/clojurethai/permalink/1231413573563800/

Advertisements

เลือกพฤติกรรมของฟังก์ชันด้วยพารามิเตอร์ฟังก์ชัน

Clojure เป็น functional language ซึ่งหมายความว่าเราสามารถส่งฟังก์ชันเป็นพารามิเตอร์ได้ ตัวภาษาได้มีการออกแบบไลบราลีมาตรฐานโดยใช้ประโยชน์จากคุณสมบัตินี้ ทำให้เราสามารถส่งฟังก์ชันเข้าไปในฟังก์ชันเพื่อเลือกพฤติกรรมที่ต้องการได้ ตัวอย่างฟังก์ชันที่ถูกออกแบบมาในลักษณะนี้ได้แก่

ผมขอยก merge-with ขึ้นมาเป็นตัวอย่างเพื่ออธิบาย
 
Clojure มีฟังก์ชัน merge ที่ใช้รวม map มากกว่า 2 อันเข้าด้วยกัน โดยหากมี key ที่ซ้ำกันระหว่าง map จะทำการใช้ value จาก map อันสุดท้าย

แต่การเลือกเอาค่าสุดท้ายไม่ได้เป็นสิ่งที่เราต้องการเสมอไป Clojure จึงมีฟังก์ชัน merge-with ให้เราเลือกใช้หากเราต้องการพฤติกรรมเมื่อมี key ซ้ำกันที่แตกต่างออกไปจาก merge ปกติ เช่น
เราสามารถเลือกรวม vector เช่นนี้ได้โดยใช้ concat ช่วย

(merge-with concat {:a [1 2 3]} {:a [4 5 6]})
;=> {:a (1 2 3 4 5 6)}
 หรือจะเลือกเอาค่าที่มากที่สุดโดยการส่ง max เข้าไป
 
(merge-with max {:a 1} {:a 3} {:a 2}) 
;=> {:a 3} 
นอกจากจะมีคู่ merge & merge-with แล้ว ฟังก์ชันอื่นๆ ด้านบนก็มีคู่ในลักษณะเดียวกัน partition & partition-by, split & split-with, assoc & update, assoc-in & update-in, sort & sort-by

จะเห็นได้ว่าการเขียนโปรแกรมในลักษณะนี้ ทำให้เกิดโค้ดที่มีพฤติกรรมใหม่ๆ ได้มากมายไม่จำกัด โดยเราแทบจะไม่ต้องเขียนอะไรเพิ่มขึ้นเลย ผมว่านี่แหละเป็น code reuse ที่เราโปรแกรมเมอร์พยายามทำให้เกิดในโปรแกรมที่เราเขียน และนี่เป็นหนึ่งในสาเหตุที่ทำให้โปรแกรมที่เขียนในลักษณะ functional สามารถสั้นกว่าโปรแกรมที่เขียนในลักษณะอื่นได้ ด้วยการทำให้เกิดการรวมกันของฟังก์ชัน (composability) เพื่อเกิดเป็นโปรแกรมที่มีพฤติกรรมใหม่ๆ ตามต้องการได้ง่าย

หวังว่าตัวอย่างเหล่านี้จะช่วยเพิ่มความเข้าใจในประโยชน์ของ functional programming มากขึ้นนะครับ

Guideline ในการเขียนเทสของผม

ทุกๆครั้งเวลาที่จะเขียนเทสสิ่งที่ผมคิดอยู่เสมอคือ การเขียนเทสในลักษณะใดที่จะทำให้เทสสร้างความมั่นใจให้แก่เราได้สูงสุด ในขณะที่เทสนั้นมีต้นทุนต่ำที่สุด

แนวทางในการเขียนเทสให้ได้แบบนั้น มีดังนี้

  • เทสต้องรันได้เร็ว ถ้ามันช้าเราจะไม่อยากรัน ไม่อยากเขียนเพิ่ม
  • เทสต้องดูแลได้ง่าย ซึ่งหมายถึง
    • เขียนง่าย การ setup ต้องไม่ซับซ้อน
    • อ่านง่าย ชัดเจนว่าต้องการทดสอบอะไร
    • faill เมื่อควรจะ fail จริงๆ
    • ไม่ fail แบบ random
  • เขียนให้น้อยที่สุดที่ตราบที่เรายังมั่นใจเวลาเราจะแก้โค้ด ตราบที่เรายังมั่นใจเวลาเราจะ deploy
    • ยิ่งปริมาณเทสเยอะยิ่งมีแต่วันที่มันจะรันช้าลง
    • ถ้าเราไม่เทสตรงนี้ ความเสียหายคืออะไร เรายอมรับได้มั้ย ถ้าเราพบภายหลังสามารถแก้ไขได้ยากหรือง่ายเพียงใด
    • บางจุดที่ถ้ามันมี error หรือ bug เราจะรู้หรือเห็นได้ทันที ผมก็ไม่เขียนเทส

กำลังจะอ่าน Maybe Haskell

กำลังจะเริ่มอ่านหนังสือเล่มนี้ http://maybe-haskell.com/ ไม่คิดมาก่อนว่าจู่ๆ จะซื้อหนังสือ Haskell มาอ่าน แต่ไปหลงพลัง marketing ของคนเขียน จากบทสัมภาษณ์ใน podcast นี้ http://giantrobots.fm/137

เค้าเล่าว่าหนังสือเล่มนี้เล่า Haskell ในวิธีที่ต่างจากเล่มอื่นโดยพยายามอธิบายถึง Functor, Applicative และ Monad ซึ่งผมรู้สึกว่าตรงกับความต้องการพอดี

ส่วนตัวมีความหลังฝังใจกับ Functor นิดหน่อยสมัยพยายามเรียน Haskell เมื่อ 5 ปีที่แล้ว ตอนนั้นเรียนจาก video ชุดนี้ http://channel9.msdn.com/Series/C9-Lectures-Erik-Meijer-Functional-Programming-Fundamentals จำได้ว่าเข้าใจเนื้อหาโดยตลอด จนกระทั่งถึงเรื่อง Functor ที่ไม่เข้าใจเลยทำให้เลิกดู video ต่อไป เลยคาดหวังว่าหนังสือเล่มนี้จะแก้เรื่องที่ค้างใจนี้ได้

อีกแรงจูงใจหนึ่งที่อยากศึกษา Haskell ช่วงนี้ เพราะตั้งแต่ต้นปีมานี้ เริ่มเขียน Clojure ในงานมากขึ้น แล้วเริ่มรู้สึกว่าในบางจุด code maintain ยาก สาเหตุหนึ่งน่าจะเป็นเพราะแบ่ง pure function กับ state ได้ไม่ค่อยดี เลยคิดว่าถ้าได้ศึกษา Haskell ดูวิธีการจัดวาง code ที่แยก side-effect ออกซักหน่อย อาจจะพอได้ไอเดียในการจัดวาง code ใน Clojure มากขึ้น

ถ้ามีโอกาสอ่านได้อ่านจนจบแล้วผลลัพธ์เป็นยังไง จะมาเล่าให้ฟังอีกทีครับ

ปล. ถ้าใครสนใจหนังสือเล่มนี้ ใน podcast page มี link สำหรับลด 50% ด้วยครับ

สรุป The Recipe for the World’s Largest Rails Monolith

เค้าว่าระบบเค้าเป็น Rails app ที่ใหญ่สุดในโลก มาเล่าเรื่องการ scale ให้ฟังอย่างสนุกสนาน
– เขียน auto scaling
– เขียน deploy tool ใหม่
– เขียน activerecord adapter สำหรับ connect multiple databases
– เขียน tool สำหรับเอา spec ไปรันบน aws spot instance
– เขียน database cleaner ใหม่สำหรับ clean เฉพาะ table ที่ถูกแตะตอน test
– เขียน database migration tool ใหม่
– เขียน component framework ใหม่
– เริ่มเขียนปี 2007 ตอน rails 1.x, upgrade มาเรื่อยๆจนตอนนี้ 4.1 แล้ว upgrade โดยการทำ shadow server เปรียบเทียบ output ของ version เก่าและใหม่

[Presentation Summary] A Tale of Three Trees (Git)

A Tale of Three Trees

Presentation นี้ ชื่อมันอาจจะไม่สื่อถึง Git และไม่ดึงดูดให้สนใจเท่าไหร่ แต่เนื้อหาดีมากครับ

ผู้พูดทำงานอยู่ Github และเป็นคนทำเว็บไซต์ 3 อันนี้ git-scm.comgitref.orgprogit.org 

ต้นไม้ 3 ต้นที่เค้าพูดถึง คือ 3 ต้นไม้ส่วนประกอบสำคัญของ Git ได้แก่

  1. ต้นไม้ HEAD
  2. ต้นไม้ Index
  3. ต้นไม้ Working directory

เค้าเริ่มจากการอธิบายต้นไม้ 3 ต้นนี้

จากนั้นอธิบายถึงคำสั่ง git reset ว่า default, –soft, –hard ทำงานภายในอย่างไร ทำให้เข้าใจว่าทำไมเค้าถึง design คำสั่งออกมาแบบนี้ (แต่ก็รู้สึกว่าเป็นวิธีคิดแบบโปรแกรมเมอร์จริงๆ ทำให้อาจจะไม่เหมาะสำหรับ first impression)

การทำงานของ –soft จะเป็น subset ของการทำงานของ default และการทำงานของ default จะเป็น subset ของการทำงานของ –hard

  • –soft จะอัพเดต HEAD และ current branch
  • default จะอัพเดต HEAD, current branch และ Index
  • –hard จะอัพเดต HEAD, current branch, Index, และ working directory

ผู้พูดได้ blog เรื่องส่วนนี้ไว้ที่ progit blog ด้วย

ตรงนี้ทำให้เข้าใจคำถามที่คาใจอยู่นานว่า ประโยชน์ของ Index มันเยอะเพียงพอให้ใส่เข้ามาในตัว tool เพื่อแล้วกลายเป็นต้องเพิ่มขั้นตอนในการทำงานขึ้นอีก 1 ขั้น จริงๆ หรือ

จากนั้น เค้าพูดต่อถึงเรื่อง git checkout ว่าคล้าย reset แต่เป็นการอัพเดต HEAD โดยไม่ได้อัพเดต current branch

จากนั้นก็เริ่มลงไปที่ internal command ของ git พร้อมกับการ demo บนจอซึ่งไม่ได้ capture มาด้วย + คนพูดๆ เร็วมากเลยฟังไม่ค่อยรู้เรื่องเท่าไหร่

ปล. ใครเจอปัญหา commit หายจาก reset –hard, git reflog และ git checkout ช่วยท่านได้นะครับ แต่ working directory หายนี่ ตัวใครตัวมัน

[ไปฟังมา] Python Memory Model

เสาร์นี้กำลังจะมีงาน Google DevFests ที่สิงคโปร์ ทาง Python group ที่นี่เลยได้โอกาส เชิญ Wesley Chun ที่บินมาร่วมงานด้วย ให้จัดพูดซักหน่อย (ถ้าผมเข้าใจไม่ผิด เค้าอยู่ทีม App Engine)

ตัว Wesley Chun นี้ผมเคยดู presentation ของเค้าครั้งนึง จากงาน Google I/O 2011 อันนี้ครับ Google I/O 2011: Python@Google

วันนี้เค้าพาพูดถึงเรื่อง Memory Model ของ Python เช่น มีตารางบอกว่าแต่ละ type มี model แบบใด และก็มีแทรก quiz ง่ายๆ เกี่ยวกับการ assign ค่าในแบบต่างๆ บน Python ที่มักทำให้เกิด bug 

เช่น กรณีนี้

และเค้าก็เล่าถึง implement แปลกๆ ภายในตัว Python เช่น

เลขที่ใช้บ่อยจะมี instance เดียวเสมอ ถูกสร้างไว้ตั้งแต่แรก ส่วนเลขทศนิยมประหลาดๆ ถ้าถูกอ้างถึงทีก็จะถูกสร้าง object ใหม่ที (ใน Python เลขเป็น immutable type) (ตั้งใจจะถ่ายสไลด์มาให้ดูแต่ถ่ายไม่ทัน) เค้ายังเล่าว่าสาเหตุของเรื่องนี้ เกิดตั้งแต่สมัย Python เวอร์ชั่น 1 กว่าๆ  ที่ตอนนั้นกำลังสู้กับ​ Perl อยู่ในเรื่อง performance จึงเกิด optimization แบบนี้ขึ้น

อีกเรื่องหนึ่งที่เค้าพูดถึงคือ object reference count ที่เมื่อ object ถูก assign ให้ตัวแปรหนึ่งที ก็จะ +1 เวลาไม่ถูกอ้างถึงก็จะ -1 จนถ้าเป็น 0​ ก็จะโดน garbage collector เคลม memory กลับไป แล้วเค้าก็ลอง run command เช็ค reference count ให้ดูกับพวก object พื้นฐานต่างๆ เช่น 1, True, False ก็ได้เลขเป็นหลักสิบหลักร้อยเลยก็มี เพราะเค้ารัน Python shell บน ui ที่เขียนด้วย Python ด้วย

ท้าย presentation มีข้อสรุปนึงที่โดนใจ เค้าบอกว่าสาเหตุของ bug เกี่ยวกับเรื่องพวกนี้ส่วนใหญ่เกิดจาก mutability เห็นมั้ยครับ ขนาดคนใช้ ภาษาที่ mutate ตัวแปรได้ยังบอกอย่างงี้เลย จะไม่ให้พวกคนใช้ภาษา functional บ้า immutability ได้ไง

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

ปล. หลายๆ คนคงคาดหวังภาพ office Google ขอโทษด้วยนะครับ ไม่มีเวลาถ่ายเลย ไปถึงสายแล้ว เพราะหาตึกไม่เจอ แถมเข้ายากด้วย ต้อง scan บัตรรายคน