สำหรับบทความนี้ ผมอยากจะมาแนะนำให้รู้จักกับ web ที่่มีชื่อว่า http://www.addedbytes.com ซึ่งมีความน่าสนใจตรงที่ web แห่งนี้จะเก็บรวบรวม Cheat Sheet ต่างๆที่น่าสนใจเอาไว้ให้เราสามารถ Download ไปใช้งานได้ฟรี ซึ่งมีอยู่ค่อนข้างเยอะครับ สำหรับผู้ที่สนใจลอง click เข้าไปดูได้ที่นี่ครับ http://www.addedbytes.com/cheat-sheets/
แหล่งที่มา: http://www.addedbytes.com
"Development should be a creative experience that you enjoy, not something that is painful." - Laravel
Monday, 30 July 2012
10 ways to format time and date using JavaScript
สำหรับบทความที่จะนำมาแนะนำไว้วันนี้ เป็นเรื่องเกี่ยวกับภาษา JavaScript กับ วิธีการจัดรูปแบบของวันที่และเวลา โดยบทความนี้มีชื่อว่า "10 ways to format time and date using JavaScript" ซึ่งผมนำมาจาก Blog ของ http://www.webdevelopersnotes.com ซึ่งแนะนำวิธีใช้งานไว้ค่อนข้างละเอียด อ่านแล้วใช้งานได้แน่นอน สำหรับใครที่ชอบสับสนเรื่องการใช้งาน Function ที่เกี่ยวกับวันที่และเวลาเหมือนอย่างผม บทความนี้น่าจะพอช่วยได้ครับ
แหล่งที่มา: http://www.webdevelopersnotes.com
Sunday, 29 July 2012
Standard Web Banners
สำหรับบทความนี้ อยากจะมาแนะนำเกี่ยวกับขนาดมาตรฐานของ Banner ที่ใช้กันบน Website ซึ่งมีศัพท์เฉพาะสำหรับเรียก Banner แต่ละขนาดแตกต่างกันไป ตาม list ดังต่อไปนี้ครับ
ส่วน list ที่อยู่ข้างล่างต่อไปนี้ เป็นขนาดที่พบเห็นโดยทั่วไป แต่ไม่ใช่ขนาดมาตรฐานครับ
แหล่งที่มา: http://designerstoolbox.com/designresources/banners/
แหล่งที่มา: http://designerstoolbox.com/designresources/banners/
Thursday, 26 July 2012
Improving Disk I/O in PHP Apps
สำหรับอันนี้เป็นบทความที่มีชื่อว่า "Improving Disk I/O in PHP Apps" เขียนไว้โดย Rodney Rehm เกี่ยวกับเทคนิคในการลด Disk I/O ใน PHP ที่เค้านำมาใช้ในการปรับปรุง Smarty version 3.1.0 ในบทความจะพูดถึงการหลีกเลี่ยงการ access Hard Disk โดยไม่จำเป็น โดยเค้าได้พูดเปรียบเทียบถึงการ access Hard Disk ไว้ดังนี้ครับ "Compared to the CPU any hard disk (yes, even SSDs) are turtles chained to a rock" ในบทความมีเทคนิคที่น่าสนใจอย่างเช่น วิธีการหลีกเลี่ยงการใช้งาน file_exists() มีประโยชน์ ลองอ่านดูแล้วกันนะครับ
แหล่งที่มา: http://blog.rodneyrehm.de/archives/12-Improving-Disk-IO-in-PHP-Apps.html
AJAX Loader Image Generator
สำหรับใครที่อยากได้ AJAX Loader Image (รูป Animation ที่แสดงการทำงานระหว่างที่เรากำลังรอ Response จาก AJAX Request) แต่ไม่อยากทำเอง หรือทำเองไม่เป็น ต้องใช้บริการ Web นี้ครับ http://ajaxload.info ที่นี่เค้ามีบริการ Generate AJAX Loader Image เองแบบ Online สามารถเลือกสี Foreground, Background หรือเลือก Transparent ได้ มีแบบให้เลือกอยู่ประมาณนึง ไม่เยอะเท่าไหร่ แต่ก็เพียงพอต่อการใช้งานครับ ลองใช้บริการดูเองละกันนะครับ
แหล่งที่มา: http://ajaxload.info
Tuesday, 24 July 2012
jQuery Image Load Plugin
สำหรับใครที่เขียน jQuery เพื่อจับ event "load" ของ image แล้วบางครั้งได้รับบ้างไม่ได้รับบ้าง สาเหตุก็เนื่องมาจากว่าบาง Browser จะไม่ trigger event ดังกล่าว ในกรณีที่เป็น cached image สำหรับวิธีแก้ปัญหาให้ลองใช้ plugin ตัวนี้ดูครับ มีชื่อว่า jquery.imgloaded พัฒนาโดย Paul Irish ซึ่งพัฒนาขึ้นมาเพื่อแก้ปัญหาดังกล่าวโดยเฉพาะครับ
แหล่งที่มา: https://github.com/peol/jquery.imgloaded/blob/master/ahpi.imgload.js
แหล่งที่มา: https://github.com/peol/jquery.imgloaded/blob/master/ahpi.imgload.js
Saturday, 21 July 2012
Simple JavaScript Inheritance
สำหรับอันนี้เป็นบทความเกี่ยวกับการใช้งาน inheritance ในภาษา JavaScript ที่มีชื่อว่า "Simple JavaScript Inheritance" เขียนโดย John Resig (เป็นคนที่่พัฒนา jQuery) มีเทคนิคหลายอย่างที่น่าศึกษาครับ สำหรับผู้ที่สนใจสามารถเข้าไปอ่านบทความได้ที่นี่ครับ http://ejohn.org/blog/simple-javascript-inheritance/
แหล่งที่่มา: http://ejohn.org/blog/simple-javascript-inheritance/
Regular Expressions
ถ้าให้ผมจัดอันดับสิ่งมหัศจรรย์ของโลกในเชิง Programming ผมเชื่อว่า Regular Expression จะต้องอยู่หนึ่งในนั้นอย่างแน่นอน สำหรับใครที่เคยใช้ Regular Expression มาก่อน น่าจะเข้าใจได้ดี แต่ด้วยความ Flexible ที่มีอย่างมากมายก็มักจะแลกมาด้วยความซับซ้อนในการใช้งาน
สำหรับผม นานๆจะหยิบมาใช้ที แต่สุดท้ายก็ลืม Syntax ไปแล้ว วันนี้ก็เลยอยากจะเอา link ที่แนะนำการใช้งานเกี่ยวกับ Regular Expression มา post ไว้ เผื่อวันไหนลืมอีก อย่างน้อยก็จะได้กลับมาดู สำหรับใครที่สนใจ ก็ลองดูตาม link ข้างล่างที่แล้วกันนะครับ (ถ้าหากเจอ link ไหนที่ดีๆ ก็จะกลับมา update เพิ่มไว้นะครับ)
Regular Expression - User Guide
http://www.zytrax.com/tech/web/regex.htmRegular Expression - Basic Syntax Reference
http://www.regular-expressions.info/reference.html/
regular-expressions.info
http://www.regular-expressions.info/
Thursday, 19 July 2012
Dijkstra's Algorithm example
สำหรับบทความต่อไปนี้จะเป็นการแนะนำในเรื่องของ Dijkstra's Algorithm ซึ่งถูกนำมาใช้ในการหา Shortest Path ใน Graph Structure ระหว่าง Node หนึ่งไปยังอีก Node หนึ่งโดยใช้วิธีการปรับค่าระยะทางที่ดีที่สุดไปเรื่อยๆ ซ้ำไปซ้ำมา จนได้ค่าระยะทางที่ดีที่สุด
ซึ่งในความเป็นจริงแล้ว Dijkstra's Algorithm ไม่ได้ตอบกลับมาเป็น Path ที่สั้นที่สุด แต่จะตอบกลับมาเป็นระยะทางที่สั้นที่สุดเท่านั้น เดี๋ยวลองดู slide อธิบายเกี่ยวกับ Dijkstra's Algorithm กันนะครับ (เป็น clip ที่ผมาเอามาจาก YouTube posted ไว้โดย bactac) ค่อยๆดูไป pause ไปทีละ Slide แล้วพยายามทำความเข้าใจครับ
แหล่งที่มา: http://www.youtube.com/watch?v=UG7VmPWkJmA&feature=related
ซึ่งในความเป็นจริงแล้ว Dijkstra's Algorithm ไม่ได้ตอบกลับมาเป็น Path ที่สั้นที่สุด แต่จะตอบกลับมาเป็นระยะทางที่สั้นที่สุดเท่านั้น เดี๋ยวลองดู slide อธิบายเกี่ยวกับ Dijkstra's Algorithm กันนะครับ (เป็น clip ที่ผมาเอามาจาก YouTube posted ไว้โดย bactac) ค่อยๆดูไป pause ไปทีละ Slide แล้วพยายามทำความเข้าใจครับ
แหล่งที่มา: http://www.youtube.com/watch?v=UG7VmPWkJmA&feature=related
Graph Implementation
สำหรับบทความนี้ ผมอยากจะมาแนะนำเกี่ยวกับทฤษฎีพื้นฐานเกี่ยวกับ Graph Data Structure ในส่วนของ Graph Implementation ซึ่งจะพูดถึงการนำ Graph ที่อยู่ในชีวิตประจำวัน มาแปลงเป็น Data Structure ในรูปแบบของ Graph สำหรับรูปแบบที่นิยมใช้งานมีอยู่ด้วยกัน 2 แบบ คือ แบบ Adjacency Metrix และแบบ Adjacency List
สำหรับ video ที่จะนำมาแสดงให้ดูต่อไปนี้ เป็น video ที่แนะนำในเรื่องของ Graph Implementation ทั้ง 2 รูปแบบ (เป็น video ที่เอามาจาก YouTube posted ไว้โดย distanceedjohn) ก็สั้นๆครับ ไม่ยาวมาก 7 นาทีกว่าๆ อธิบายเข้าใจง่ายครับ
แหล่งที่มา: http://www.youtube.com/watch?feature=endscreen&NR=1&v=2guA5uMEmZQ
สำหรับ video ที่จะนำมาแสดงให้ดูต่อไปนี้ เป็น video ที่แนะนำในเรื่องของ Graph Implementation ทั้ง 2 รูปแบบ (เป็น video ที่เอามาจาก YouTube posted ไว้โดย distanceedjohn) ก็สั้นๆครับ ไม่ยาวมาก 7 นาทีกว่าๆ อธิบายเข้าใจง่ายครับ
แหล่งที่มา: http://www.youtube.com/watch?feature=endscreen&NR=1&v=2guA5uMEmZQ
Graph Traversal
Graph เป็น Data Structure ประเภทหนึ่ง ซึ่งประกอบไปด้วย Node (หรือเรียกว่า Vertex) และ Relationship (หรือเรียกว่า Arc) สำหรับบทความนี้ ผมอยากแนะนำเรื่อง Graph Traversal (การ visit แต่ละ Node ใน Graph Structure) ซึ่งที่นิยมใช้งาน มีอยู่ 2 แบบคือ แบบ Depth-First Search (DFS) (ในการ implement มักจะใช้ Stack) และแบบ Breadth-First Search (ในการ implement มักจะใช้ Queue)
สำหรับการ Traversal ในแบบ Depth-First Search จะใช้วิธีการ travel ไปในแต่ละ Branch ของ Tree ทีละ Branch จนจบ แล้วถึงจะ Travel ไปใน Branch ถัดไป ยกตัวอย่างเช่น Tree ของเรามี 2 branch คือ ด้านซ้ายและด้านขวา Depth-First Search อาจจะเริ่ม Travel ใน Branch ฝั่งซ้ายก่อน และจะ Travel จนครบทุก Node ใน Branch ฝั่งซ้าย เมื่อครบแล้วถึงจะไปเริ่ม Travel ต่อใน Branch ฝั่งขวา
สำหรับการ Traversal ในแบบ Breadth-Firsh Search จะใช้วิธีการ travel เป็นแบบลำดับชั้น สมมุติว่าเรามีโครงสร้างแบบ Tree ที่มี 3 ลำดับชั้น คือ Root , Level-1 และ Level-2 การ Traversal ในแบบ Bread-First Search จะ travel ไปทีละลำดับชั้นจบครบทุก Node เมื่อครบแล้วถึงจะเริ่ม Travel ต่อใน Level ถัดไป
สำหรับ video ต่อไปนี้ เป็น video (เอามาจาก YouTube posted ไว้โดย soetamrizky) ที่แนะนำการ implement Graph Traversal ทั้ง 2 รูปแบบ อธิบายสั้นๆ เข้าใจง่าย ใช้เวลาดูไม่นานครับ
แหล่งที่มา:
สำหรับการ Traversal ในแบบ Depth-First Search จะใช้วิธีการ travel ไปในแต่ละ Branch ของ Tree ทีละ Branch จนจบ แล้วถึงจะ Travel ไปใน Branch ถัดไป ยกตัวอย่างเช่น Tree ของเรามี 2 branch คือ ด้านซ้ายและด้านขวา Depth-First Search อาจจะเริ่ม Travel ใน Branch ฝั่งซ้ายก่อน และจะ Travel จนครบทุก Node ใน Branch ฝั่งซ้าย เมื่อครบแล้วถึงจะไปเริ่ม Travel ต่อใน Branch ฝั่งขวา
สำหรับการ Traversal ในแบบ Breadth-Firsh Search จะใช้วิธีการ travel เป็นแบบลำดับชั้น สมมุติว่าเรามีโครงสร้างแบบ Tree ที่มี 3 ลำดับชั้น คือ Root , Level-1 และ Level-2 การ Traversal ในแบบ Bread-First Search จะ travel ไปทีละลำดับชั้นจบครบทุก Node เมื่อครบแล้วถึงจะเริ่ม Travel ต่อใน Level ถัดไป
สำหรับ video ต่อไปนี้ เป็น video (เอามาจาก YouTube posted ไว้โดย soetamrizky) ที่แนะนำการ implement Graph Traversal ทั้ง 2 รูปแบบ อธิบายสั้นๆ เข้าใจง่าย ใช้เวลาดูไม่นานครับ
แหล่งที่มา:
Why is `ereg` deprecated in PHP ?
การใช้งาน ereg() ใน PHP |
ผมคิดว่าหลายๆคนที่เขียน PHP แล้วเจอกับปัญหา "ereg() is deprecated" (ใน PHP version 5.3.0 เป็นต้นไป) น่าจะเกิดความสงสัย (เหมือนกับผม) ว่าทำไมถึง deprecated
สาเหตุที่ PHP ตัดสินใจเลิกใช้งาน ereg() เพราะว่าอยากจะให้ใช้ PCRE (Pearl Compatible Regular Expression) Extensions แทน เพราะว่าโดยทั่วไปจะมีประสิทธิภาพที่ดีกว่า (แต่ไม่เสมอไป ในบาง function ereg() ก็สามารถทำงานได้เร็วกว่า) ยกตัวอย่างเช่น function preg_match() ซึ่งใช้ PCRE syntax จะทำงานได้เร็วกว่า function ereg() สำหรับในบาง post ก็พูดถึงสาเหตุของการที่ PHP ยกเลิกใช้งาน ereg() ว่าเป็นเพราะใน PHP 6.0 ได้มีการพัฒนาในส่วนของการรองรับ Unicode ขึ้นมาใหม่ ซึ่งน่าจะเป็นสาเหตุหลักที่ทำให้ ereg() ไม่สามารถใช้งานได้
สำหรับ PHP ตั้งแต่ version 6.0 เป็นต้นไป ได้ตัด function ereg() ออกไปเป็นที่เรียบร้อยแล้วนะครับ ถ้าหากว่าใครที่มีแนวโน้มว่าจะต้อง upgrade ไปใช้ PHP 6.0 ควรหลีกเลี่ยงการใช้งาน ereg() นะครับ
แหล่งที่มา:
- http://stackoverflow.com/questions/3078993/why-is-ereg-deprecated-in-php
- http://stackoverflow.com/questions/1361591/php-ereg-vs-preg
Wednesday, 18 July 2012
Design Pattern - FlyWeight Pattern
ห้องสมุดก็มีการใช้ FlyWeight Pattern |
หากพูดคำว่า FlyWeight Pattern หลายๆคนอาจจะไม่รู้จัก แต่ถ้าพูดถึงคำว่า "ห้องสมุด" คิดว่าหลายๆคนน่าจะคุ้นเคยมากกว่า เราเคยสงสัยหรือไม่ว่า ทำไมห้องสมุดสามารถให้บริการแก่ผู้ใช้จำนวนมากได้ ทั้งๆที่หนังสือก็ไม่ได้มีจำนวนเล่มเท่ากับจำนวนผู้มาใช้บริการ
เหตุผลที่ห้องสมุดสามารถให้บริการแก่ผู้ใช้จำนวนมาก ก็คือ ในขณะใดขณะหนึ่งมีจำนวนผู้ใช้ที่ต้องการอ่านหนังสือเล่มเดียวกันเพียงแค่จำนวนหนึ่ง (อาจจะ 4-5 คน แล้วแต่ความนิยมของหนังสือ) ทำให้ห้องสมุดเพียงแค่จัดหาหนังสือให้เพียงพอกับความต้องการใช้บริการในขณะเดียวกันก็เพียงพอแล้ว เพราะเมื่อผู้ใช้บริการแต่ละคนใช้บริการเสร็จ ก็จะนำหนังสือไปคืน ทำให้ผู้ใช้บริการคนอื่นสามารถใช้บริการได้อีก ซึ่งเป็นเทคนิคเดียวกันกับที่ใช้ใน FlyWeight Pattern นั่นเอง
FlyWeight Pattern เป็นเทคนิคในการนำ Object ที่สร้างไว้แล้ว กลับมาใช้ใหม่ โดยการสร้าง Object ใน FlyWeight Pattern จะทำผ่าน FlyWeight Factory ซึ่งจะทำหน้าที่บริหารการสร้าง instance (โดยการใช้ Object Pool เข้ามาช่วย) ซึ่งจะช่วยให้เราใช้ Memory ได้อย่างมีประสิทธิภาพ สำหรับภาพที่จะแสดงให้ดูต่อไปนี้เป็น UML Diagram สำหรับ FlyWeight Pattern
FlyWeight Pattern UML Diagram |
จาก Diagram ข้างต้น จะเห็นว่า FlyWeight Factory จะมี Pool สำหรับเก็บ Object (ในที่นี้คือ FlyWeight Object) อยู่ภายใน ในการใช้งาน Client จะทำการสร้าง Object ผ่าน method ที่ชื่อว่า getFlyWeight() ของ FlyWeightFactory (ซึ่งใน method นี้จะมีการ implement logic ในการนำ Object ที่อยู่ใน pool กลับมาใช้ใหม่)
FlyWeight Pattern เหมาะสำหรับระบบที่มีการสร้าง Object ชนิดเดียวกันจำนวนมากๆ เพราะจะสามารถ Utilize การใช้ object pool ได้อย่างเต็มที่ สำหรับผู้ที่สนใจศึกษาเพิ่มเติม สามารถดู Source Code ที่ implement FlyWeight Pattern ได้ที่นี่ครับ http://en.wikipedia.org/wiki/Flyweight_pattern
แหล่งที่มา: http://en.wikipedia.org/wiki/Flyweight_pattern
Design Pattern - Proxy Pattern
บริการตัวแทนไปรษณีย์ ก็คือ Proxy Service รูปแบบหนึ่ง |
หากพูดถึงคำว่า Proxy หลายๆคนที่ไม่ได้คุ้นเคยกับระบบ Network อาจจะไม่ค่อยคุ้นเคยเท่าที่ควร หรืออาจจะเคยได้ยินชื่อ แต่ไม่รู้ว่ามันคืออะไร คำว่า Proxy แปลเป็นภาษาไทยว่า "ผู้แทน" หรือ "ผู้รับมอบฉันทะ" (แปลจาก dictionary ของ Lexitron)
สำหรับในชีวิตประจำวันของเรา มีบริการหลายๆอย่างที่เป็น Proxy Service ยกตัวอย่างเช่นบริการไปรษณีย์ เราสามารถส่งจดหมายหรือพัสดุโดยไม่ต้องไปที่ไปรษณีย์ด้วยตนเอง เพียงแค่ใช้บริการตัวแทนไปรษณีย์ที่อยู่ตามอาคารสำนักงานใหญ่ๆ หรือตามห้างสรรพสินค้า ซึ่งจะสามารถช่วยแบ่งภาระของไปรษณีย์ไทยในการรองรับผู้ใช้บริการในสถานที่ต่างๆไปได้มาก สำหรับผู้ใช้บริการเองก็สะดวก เพราะไม่ต้องเดินทางไปที่ไปรษณีย์เอง ทำให้ประหยัดเวลาและค่าใช้จ่าย
Proxy Server |
จะเห็นได้ว่าที่จริงแล้วเราคุ้นเคยกับ Proxy Service เหล่านี้มานานแล้ว เพียงแค่เราไม่รู้ว่ามันคือ Proxy Service ซึ่งแนวคิดของ Proxy Pattern ก็คือ การมอบหมายให้ Class หนึ่งทำหน้าเป็น "ตัวแทน" สำหรับอีก Class หนึ่ง เดี๋ยวผมจะลองยกตัวอย่างในกรณีของ Server ที่ทำหน้าที่เป็น Reverse Proxy ให้ดูนะครับ Reverse Proxy คือ Server ที่รับ Request จาก internet เอาไว้ ก่อนที่จะส่งไปให้ Real Server จริงอีกทีหนึ่ง ซึ่ง Reverse Proxy อาจจะใช้ในการตรวจสอบ Request หรือใช้ในการเปลี่ยนแปลงข้อมูลของ Request ก่อนที่จะส่งไปให้กับ Real Server หรือบางครั้งก็สามารถ Response แทน Real Server ได้ ทั้งนี้เพื่อช่วยลดภาระในการทำงานและเพิ่มความปลอดภัยให้กับ Real Server
เช่นเดียวกัน ในแง่ของการพัฒนาโปรแกรม Proxy Class ก็จะทำหน้าที่รับ Request จาก Client ก่อนที่จะเรียก Real Class จริงๆให้ทำงานต่อไป เดี๋ยวมาลองดู UML Diagram กันก่อนแล้วกันนะครับ
Proxy Pattern UML Diagram |
จากใน Diagram จะเห็นว่าทั้ง Proxy และ RealSubject ต่างก็ implement Subject interface และยังแสดงให้เห็นว่า Proxy มีการ delegate request ไปยัง RelSubject class ให้สังเกตุว่า Client จะมีการ interact กับ Subject interface นั่นหมายความว่า Client สามารถทำงานได้กับทั้ง Proxy และ RealSubject
เราสามารถนำ Proxy Pattern ไปประยุกต์ใช้งานในกรณีที่เราจำเป็นต้องใช้งาน Complex Object หลายๆตัวใน Application ซึ่งแทนที่เราจะสร้าง Complex Object ขึ้นมาหลายๆตัว (ซึ่งเป็นการสิ้นเปลือง Memory) เราสามารถสร้าง Complex Object เพียงแค่ตัวเดียว แต่สร้าง Proxy Object ขึ้นมาหลายๆตัวแทน (ซึ่งจะประหยัด Memory มากกว่า) โดยให้ Proxy แต่ละตัวรับ request แล้ว delegate request ไปที่ Complex Object แทน
สำหรับผู้ที่สนใจศึกษาเพิ่มเติม สามารถดู Source Code ที่ implement Proxy Pattern ได้ที่นี่ครับ http://en.wikipedia.org/wiki/Proxy_pattern
แหล่งที่มา: http://en.wikipedia.org/wiki/Proxy_pattern
Design Pattern - Bridge Pattern
Wikipedia เขียนอธิบายแนวความคิดหลักของ Bridge Pattern ใเอาไว้ว่า คือการแยกส่วนของ Abstraction ออกจาก Implementation อ่านกี่ทีก็งง เอาเป็นว่าผมจะอธิบายในแบบของผมแล้วกัน
Bridge Pattern คือแนวคิดในการยืมความสามารถจาก Class ภายนอกมาใช้งาน ยกตัวอย่างเช่น Messi ได้รับการคัดเลือกให้ร่วมแข่งขัน Tennis Wimbledon แต่ Messi ตี Tennis ไม่เป็น ก็เลยโทรหา Federer ให้มาช่วย พอถึงตอนแข่ง Federer ก็เข้าสิงในร่างของ Messi ทำให้ Messi สามารถตี Tennis ได้เหมือนกับ Federer
จากตัวอย่างจะสังเกตุว่า Messi ไม่มีความสามารถในการตี Tennis แต่ Messi สามารถตี Tennis ได้ โดยยืมความสามารถดังกล่าวมาจาก Federer นั่นคือความหมายของคำว่า Bridge นั่นเอง เดี๋ยวมาลองดู UML Diagram กันแล้วกันนะครับ
จาก UML Diagram ข้างต้น ด้านซ้ายมือคือ class หลักที่เราจะนำใช้งาน ในที่นี้เราจะเรียกว่า Abstraction ส่วนด้านขวามือคือ class ที่เราจะไปขอยืมความสามารถมา ซึ่งในที่นี้จะเรียกว่า Implementor ให้สังเกตุว่า class ที่ชื่อว่า ConcreteImplementorA และ ConcreteImplementorB ต่างก็ implement Implementor interface ด้วยกันทั้งคู่ จากใน Diagram เราจะเห็นว่า Abstraction class มี "has a" relationship กับ Implementor ซึ่งหมายความว่า Abstraction class จะมี Implentor อยู่ภายในนั่นเอง นอกจากนั้นใน Diagram ยังแสดงให้เห็นว่า ใน Abstract class นั้นมีความสามารถภายในตัวอยู่ ซึ่งในที่นี้คือ method ที่ชื่อว่า operation() แต่ในขณะเดียวกันก็ยังสามารถเรียกใช้ method ที่ชื่อว่า implementation() จาก Implementor interface ได้ (เพราะมี class ที่ implement Implementor interface อยู่ภายใน)
สำหรับผู้ที่สนใจศึกษาเพิ่มเติม สามารถดู Source Code ตัวอย่างที่ implement Bridge Pattern ได้ที่นี่ครับ http://en.wikipedia.org/wiki/Bridge_pattern
แหล่งที่มา: http://en.wikipedia.org/wiki/Bridge_pattern
Bridge Pattern คือแนวคิดในการยืมความสามารถจาก Class ภายนอกมาใช้งาน ยกตัวอย่างเช่น Messi ได้รับการคัดเลือกให้ร่วมแข่งขัน Tennis Wimbledon แต่ Messi ตี Tennis ไม่เป็น ก็เลยโทรหา Federer ให้มาช่วย พอถึงตอนแข่ง Federer ก็เข้าสิงในร่างของ Messi ทำให้ Messi สามารถตี Tennis ได้เหมือนกับ Federer
จากตัวอย่างจะสังเกตุว่า Messi ไม่มีความสามารถในการตี Tennis แต่ Messi สามารถตี Tennis ได้ โดยยืมความสามารถดังกล่าวมาจาก Federer นั่นคือความหมายของคำว่า Bridge นั่นเอง เดี๋ยวมาลองดู UML Diagram กันแล้วกันนะครับ
Bridge Pattern UML Diagram |
จาก UML Diagram ข้างต้น ด้านซ้ายมือคือ class หลักที่เราจะนำใช้งาน ในที่นี้เราจะเรียกว่า Abstraction ส่วนด้านขวามือคือ class ที่เราจะไปขอยืมความสามารถมา ซึ่งในที่นี้จะเรียกว่า Implementor ให้สังเกตุว่า class ที่ชื่อว่า ConcreteImplementorA และ ConcreteImplementorB ต่างก็ implement Implementor interface ด้วยกันทั้งคู่ จากใน Diagram เราจะเห็นว่า Abstraction class มี "has a" relationship กับ Implementor ซึ่งหมายความว่า Abstraction class จะมี Implentor อยู่ภายในนั่นเอง นอกจากนั้นใน Diagram ยังแสดงให้เห็นว่า ใน Abstract class นั้นมีความสามารถภายในตัวอยู่ ซึ่งในที่นี้คือ method ที่ชื่อว่า operation() แต่ในขณะเดียวกันก็ยังสามารถเรียกใช้ method ที่ชื่อว่า implementation() จาก Implementor interface ได้ (เพราะมี class ที่ implement Implementor interface อยู่ภายใน)
สำหรับผู้ที่สนใจศึกษาเพิ่มเติม สามารถดู Source Code ตัวอย่างที่ implement Bridge Pattern ได้ที่นี่ครับ http://en.wikipedia.org/wiki/Bridge_pattern
แหล่งที่มา: http://en.wikipedia.org/wiki/Bridge_pattern
Design Pattern - Abstract Factory Pattern
Abstract Factory |
Abstract Factory Pattern คือ Design Pattern รูปแบบหนึ่งที่อยู่ในกลุ่มของ Creation Pattern ซึ่งมีแนวคิดดังนี้คือ Client ไม่จำเป็นต้องติดต่อกับ concrete Factory เพื่อสร้าง Object แต่ให้ติดต่อผ่าน abstract Factory แทน ซึ่งจะช่วยลด Dependency ระหว่าง Client และ Concrete Factory และจะส่งผลเราสามารถเพิ่มหรือเปลี่ยนแปลง Factory ได้ในภายหลัง โดยที่ไม่กระทบกับการทำงานของ client
ผมอยากกิน "ซาลาเปา Rabbit" ผมไม่สนว่าใครจะผลิตให้ผม! |
หากเราสังเกตุดีๆ เราจะพบว่าทุกๆ Design Pattern นั้นแท้จริงแล้วมันอยู่รอบๆตัวเรานี่เอง เพียงแค่เราอาจจะไม่ได้สังเกตุ ผมจะลองยกตัวอย่างที่เป็นรูปธรรมขึ้นมาหน่อย เพื่อที่จะได้เข้าใจได้ง่ายขึ้นนะครับ ยกตัวอย่างเช่น Ronaldo มาเมืองไทย อยากกินซาลาเปา Rabbit เลยเดินเข้าไปซื้อซาลาเปา Rabbit จาก 7-Eleven ซึ่ง Ronaldo จะสนใจเพียงแค่ว่าจ่ายเงินแล้วจะได้กินซาลาเปา Rabbit ซึ่ง Ronaldo ไม่สนใจว่าซาลาเปาที่ได้จะสั่งผลิตมาจากไหน จากตัวอย่างนี้ Key Message จะอยู่ที่ว่า "Ronaldo ไม่ได้สนใจว่าซาลาเปาจะผลิตมาจากไหน" ซึ่ง 7-Eleven อาจจะจ้างให้ Apple เป็นผู้ผลิต "ซาลาเปา" หรือไม่ก็จ้างให้ Samsung เป็นผู้ผลิตให้ก็แล้วแต่ ตราบใดที่ Ronaldo ไม่สนใจ
จากตัวอย่างข้างต้น Ronaldo เปรียบเสมือนกับ Client (ผู้ใช้บริการ) ส่วน 7-Evelen เปรียบเสมือน Abstract Factory จะสังเกตุว่า Ronaldo ไม่ได้สั่งซื้อ "ซาลาเปา" จาก Apple หรือ Samsung (ในที่นี้ Apple และ Sumsung ถือว่าเป็น Concrete Factory) โดยตรง แต่จะซื้อผ่าน 7-Eleven เท่านั้น จะเห็นได้ว่าในมุมมองของ Ronaldo นั้น เหมือนกับว่า 7-Eleven คือผู้ที่ผลิต "ซาลาเปา" แต่แท้ที่จริงแล้ว 7-Eleven อาจจะจ้างให้ Apple หรือ Samsung เป็นผู้ผลิตให้ก็ได้
สำหรับ Abstract Factory Pattern สามารถแสดงเป็น UML Diagram ได้ดังนี้ครับ
จากในภาพจะเห็นว่า ConcreteFactoryA และ ConcreteFactoryB ต่างก็ implement AbstractFactory interface ซึ่งตรงนี้ผมอยากจะเน้นว่า ในการใช้งานนั้น Client จะ interact กับ Abstract Factory แต่จะไม่ได้ interact กับ ConcreteFactory โดยตรง ซึ่งเป็นสิ่งที่สำคัญ เพราะจะทำให้เราสามารถเพิ่มหรือเปลี่ยนแปลง ConcreteFactory ในภายหลังได้นั่นเอง
สำหรับผู้ที่สนใจสามารถศึกษาเพิ่มเติมจาก Source Code ที่ implement Abstract Factory Pattern ได้ที่นี่ครับ http://en.wikipedia.org/wiki/Abstract_factory_pattern
แหล่งที่่มา: http://en.wikipedia.org/wiki/Abstract_factory_pattern
Tuesday, 17 July 2012
ePub Reader - The Best Alternative for Paperback Books
ปัจจุบัน E-Books เริ่มมีให้ Dowload ในรูปแบบของ ePUB กันมากขึ้น สำหรับหลายๆคนที่กำลังมองหาโปรแกรมสำหรับอ่าน ePUB บน PC อยู่ วันนี้ผมมีโปรแกรมอ่าน ePUB มาแนะนำ ชื่อว่า ePUB Reader เป็น Freeware ครับ เป็นโปรแกรมสำหรับอ่าน ePUB โดยเฉพาะ (ไม่สามารถอ่าน file ประเภท PDF หรือ file ประเภทอื่นๆได้นะครับ) แต่ที่ผมไม่ชอบอยู่อย่างนึงก็คือในขั้นตอนการติดตั้งจะถูกบังคับในติดตั้ง AVG Toolbar เข้าไปด้วย (เราเลือกไม่ติดตั้งไม่ได้นะครับ) แต่ก็ไม่เป็นไร ก็แค่ลำบากนิดหน่อย พอติดตั้งเสร็จ เราก็สามารถไป uninstall AVG Toolbar ออกจากใน Control Panel เอาเองได้ครับ สำหรับผู้ที่สนใน สามารถเข้าไป download ePUB Reader ได้ที่นี่ครับ http://epubreader.info/
แหล่งที่มา: http://epubreader.info
Dynamic 3D Art
อันนี้ไม่เกี่ยวกับ Programming นะครับ แต่เป็นความชื่นชอบส่วนตัวของผมเอง เลยอยากบันทึกเก็บไว้ใน Blog เป็นข่าวที่มาจาก Yahoo! News เกี่ยวกับ 3D Art (ผมไม่ได้อ่านเนื้อหา ดูแต่รูปอย่างเดียว) ดูแล้วช่วยเสริมสร้างจินตนาการดีครับ เลยอยากเอามาแนะนำไว้ให้ดูกัน สำหรับผู้ที่สนใจ สามารถเข้าไปดูได้ที่นี่ครับ http://yhoo.it/LoUj4X
แหล่งที่มา: http://news.yahoo.com
Design Pattern - Builder Pattern
เมื่อ พูดถึง Builder Pattern หลายๆคนอาจจะงงๆว่ามันคืออะไร จริงๆแล้ว Builder Pattern มันอยู่ในชีวิตประจำวันของเรานี่เอง มันอยู่ในข้าวผัดกระเพราไก่ครับ เดี๋ยวผมจะเล่าให้ฟังว่ามันไปอยู่ในข้าวผัดกระเพราไก่ได้ยังไง
ก่อนอื่นมาพูดถึงทฤษฎีกันก่อนแล้วกันนะครับ สำหรับ Builder เป็นหนึ่งใน Design Pattern ที่อยู่ในกลุ่มของ Creation Pattern มีหน้าที่ในการสร้าง Object แต่จะซับซ้อนกว่า Factory Method คือสำหรับ Factory Method เมื่อมีการเรียกใช้งาน ก็จะคืนค่ากลับมาในรูปแบบของ Single Object ที่เสร็จเรียบร้อย พร้อมที่จะนำไปใช้งาน แต่สำหรับ Builder Pattern นั้นจะใช้ในการสร้าง Object ที่มีความซับซ้อนมากกว่า โดยที่เราสามารถกำหนดการสร้าง Object ทีละส่วนเองได้
ผม คิดว่าทุกคนน่าจะเคยสั่งข้าวผัดกระเพราเวลาไปร้านอาหารตามสั่ง เดี๋ยวเราจะมาดูว่า Builder Pattern กับข้าวผัดกระพราไก่มันเกี่ยวข้องกันอย่างไร ปกติเวลาที่เราสั่งข้าวผัดกระพรา บางคนก็จะใส่พริก ไม่ใส่พริก เอาไข่ดาว ไม่เอาไข่ดาว ซึ่งตอนที่ทางร้านเค้ากำลังเตรียมข้าวผัดกระเพราให้เรา เรารู้หรือไม่ว่า เค้ากำลังใช้ Builder Pattern อยู่
การ ใช้ Builder Pattern จะช่วยให้เราสามารถกำหนดวิธีในการสร้าง Object (ในที่นี่คือข้าวผัดกระเพราไก่นั่นเอง) โดยขั้นตอนในที่นี้ก็อาจจะเป็น ใส่พริก ใส่ไขดาว สำหรับ Object ที่ทำหน้าที่กำหนดการทำงานในขั้นตอนี้เราจะเรียกว่า Director (ซึ่งในที่นี่ก็คือคนที่จด Order ให้เรานั่นเอง) จากนั้น Director จะสั่งให้ Builder (ในที่นี้ก็คือแม่ครัวทำหน้าที่เตรียมข้าวผัดกระเพราให้เรานั่นเอง) ทำหน้าที่สร้าง Object ตามขั้นตอนที่กำหนดไว้ สังเกตุว่าการใช้ Builder Pattern จะทำให้เราสามารถที่จะสร้าง Object ที่มีความแตกต่างกันในรายละเอียด (บางคนใส่พริก ไม่ใส่พริก บางคนเอาไข่ดาว ไม่เอาไข่ดาว) ภาพที่จะแสดงต่อไปนี้เป็นภาพที่แสดงความสัมพันธ์ระหว่าง Client, Direcotr และ Builder (เนื่องจากผมไม่สามารถหาภาพตัวอย่างที่เป็น flow ของผัดกระเพราได้ จึงขอแสดงตัวอย่างเป็น Fast Food แทนแล้วกันนะครับ)
สำหรับ ภาพที่จะแสดงต่อไปนี้ เป็น UML Diagram ของ Builder Pattern ซึ่งแสดงความสัมพันธ์ระหว่างส่วนประกอบต่างๆใน Builder Pattern ซึ่งหลักๆก็คือ Concrete Class ที่ implement Builder interface และ Director ซึ่งจะเรียกใช้งาน Builder อีกที
Builder Pattern UML Diagram |
จากใน UML Diagram เราจะเห็นว่า class BuilderType1 และ BuilderType2 มีการ implement interface ที่ชื่อว่า buildPart(), buildPart() และ getProduct() (เนื่องจาก inherit มาจาก Abstract Class ที่ชื่อว่า Builder อีกทีหนึ่ง) ส่วนต่อมาทางด้านซ้ายมือคือ class ที่มีชื่อว่า Director ซึ่งจะเรียกใช้งาน class ที่ implement Builder interface (ในที่นี้คือ BuilderType1 และ BuilderType2)
สัง เกตุว่าใน Builder Pattern นั้น class ที่ทำหน้าที่เป็น Builder นั้นจะรู้เพียงแค่วิธีการสร้างในแต่ละส่วน ของตนเองเท่านั้น แต่สำหรับขั้นตอนหรือวิธีการการสร้างจะเป็นหน้าที่ของ class ที่ทำหน้าที่เป็น Director เป็นผู้กำหนด การนำ Builder interface มาใช้ จะทำให้ class ที่ทำหน้าที่เป็น Director ไม่มีความเกี่ยวข้องกับ class ที่ทำหน้าที่เป็น Builder โดยตรง ซึ่งจะทำให้ Application ที่เราพัฒนามีความยืดหยุ่นสูง เนื่องจากเราสามารถสร้าง Builder เพิ่มขึ้นได้ในอนาคต ตราบใดที่เรายัง implement Builder interface ส่วน Client ที่ต้องการสร้าง Object จะไม่ติดต่อโดยตรงกับ Builder แต่จะสร้าง Object ผ่านทาง Director แทน
สำหรับผู้ที่สนใจ สามารถเข้าไปดู Source Code ตัวอย่าง สำหรับการ implement Builder Pattern ได้ที่นี่ครับ http://en.wikipedia.org/wiki/Builder_pattern
แหล่งที่มา: http://en.wikipedia.org/wiki/Builder_pattern
Design Pattern -Factory Pattern
การสร้าง Object โดยใช้ Factory Pattern เป็นการจำลองรูปแบบการสร้างสินค้าภายในโรงงาน คือ เวลาที่เราต้องการสินค้า เราก็จะสั่งให้โรงงานผลิต โรงงานก็จะทำหน้าที่ผลิตสินค้าให้โดยที่เราไม่ต้องสนใจว่าจะผลิตอย่างไร เช่นเดียวกัน Factory Method ก็จะทำหน้าที่สร้าง Object โดย abstract วิธีการสร้างไว้ภายใน
การนำ Factory Pattern มาใช้ในการสร้าง Object จะช่วยให้เราสามารถ Encapsulate ความซับซ้อนในกระบวนการสร้าง Object นอกจากนั้นยังเป็นการ abstract ในส่วนของการสร้าง Object โดยเราสามารถสร้าง Object ที่แตกต่างกันจาก Factory Method เดียวกัน เดี๋ยวลองมาดูตัวอย่างกันนะครับ
สำหรับตัวอย่างที่นำมาแสดงให้ดูนี้ เป็นตัวอย่างการสร้างผลไม้กระป๋อง (FruitCan) โดยภายใน class FruitCan จะบรรจุ class Fruit ไว้อีกที นอกจากนั้นยังมี factory method ที่ชื่อว่า build (ในที่นี่เราสร้างเป็นแบบ static) เอาไว้สำหรับสร้าง instance ของ FruitCan โดยที่เราสามารถส่งชื่อ class ของผลไม้ที่เราต้องการจะสร้าง (ในที่นี้คือ Mango และ Lemon) เข้าไปได้
ให้สังเกตุว่าเราสร้าง instance ของ FruitCan โดยผ่าน factory method ที่ชื่อว่า build ซึ่งจะ wrap กระบวนการสร้าง FruitCan เอาไว้ภายใน นอกจากนั้นเรายังออกแบบให้ build รับ parameter ที่เป็นชื่อ class ของผลไม้ เพื่อที่ว่าเราจะสามารถสร้าง FruitCan จากผลไม้ชนิดอื่นๆ (โดยการสร้าง class ของผลไม้เพิ่มเติมได้ในภายหลัง) ได้ในอนาคต
แหล่งที่มา: http://en.wikipedia.org/wiki/Factory_method_pattern
Monday, 16 July 2012
PHP - Config Error Reporting at Page Level
ปกติเวลาที่เราจะกำหนดรูปแบบของการแสดงผล Error ใน PHP เราจะต้องไปเปลี่ยน config ใน php.ini แต่สำหรับใครที่กำลังทดลองอยู่ ยังต้องเปลี่ยนค่าไปๆมาๆ และไม่อยากไปเปลี่ยนใน php.ini สามารถกำหนดโดยตรงใน file PHP ที่กำลัง Develop อยู่ได้เลย สำหรับรูปแบบการกำหนดค่าสามารถดูได้ตามตัวอย่างข้างล่างครับ
แหล่งที่มา: http://php.net/manual/en/function.error-reporting.php
แหล่งที่มา: http://php.net/manual/en/function.error-reporting.php
How to Use PHP Namespaces
ภาษา PHP เริ่มรองรับการใช้ Namespace ตั้งแต่ Version 5.3 ซึ่งช่วยลดปัญหาการตั้งชื่อชนกันของตัวแปร (Name Collision) สำหรับ PHP ใน Version ก่อนหน้า ที่ยังไม่รองรับ Namespace เราจะพบว่าผู้ผลิต Library ยี่ห้อต่างๆ ต่างก็พยายามหาวิธีตั้งชื่อ Library ของตนเพื่อที่จะหลีกเลี่ยงปัญหา Name Collision ที่อาจเกิดขึ้น ยกตัวอย่างเช่น WordPress จะเติม Prefix คำว่า "WP_" เข้าไปที่หน้าชื่อของ Class/Function name ส่วน Zend Framework จะใช้วิธีการตั้งชื่อที่ค่อนข้างยาวหน่อย อย่างเช่น Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive.
สำหรับบทความที่ผมจะนำมาแนะนำต่อไปนี้ เขียนโดย Craig Bukler เป็นบทความชื่อว่า How to Use PHP Namespaces, Part 1: The Basics (มีทั้งหมดด้วยกัน 3 ตอน) ซึ่งจะเขียนแนะนำการประยุกต์ใช้งาน Namespace ในภาษา PHP ซึ่งผมอ่านดูแล้วเห็นว่ามันมีประโยชน์ดีก็เลยอยากจะแนะนำเอาไว้ เผื่อว่าใครยังไม่เคยนำมาใช้ ยังไงก็ลองอ่านดูแล้วกันนะครับ
แหล่งที่มา: http://www.sitepoint.com/php-53-namespaces-basics/
Introduction to JSON and PHP
ปัจจุบันการใช้งาน JSON เริ่มที่จะเข้ามาแทนที่ XML เนื่องจากมีขนาดเล็ก สามารถใช้งานได้โดยไม่จำเป็นต้องใช้ parser ที่วุ่นวาย ผู้ที่คิดค้น JSON format คือ Douglas Crockford ดังนั้นการเรียนรู้ที่จะใช้งาน JSON จึงเป็นสิ่งที่จำเป็น โดยเฉพาะ Web Developer สำหรับบทความที่ผมอยากจะแนะนำต่อไปนี้ เขียนขึ้นโดย Frank Lakatos มีชื่อว่า "Introduction to JSON and PHP" เป็นบทความที่เขียนเกี่ยวกับการประยุกต์ใช้งานร่วมกันระหว่าง JSON และ PHP โดยมีตัวอย่างการใช้งานทั้งทางฝั่ง Client Side (โดยใช้ jQuery และ AJAX) และ Server Side (PHP และ json_encode) สำหรับผู้ที่สนใจ สามารถเข้าไปอ่านบทความได้ที่นี่ครับ http://www.itnewb.com/tutorial/Introduction-to-JSON-and-PHP
แหล่งที่มา:
PHP Try Catch Guide
สำหรับการพัฒนา Application ให้มีคุณภาพ การตรวจจับ Error เป็นสิ่งสำคัญที่เราควรไม่ควรมองข้าม การตรวจจับ Error ในภาษา PHP เราจะใช้ Try Catch สำหรับการตรวจจับข้อผิดพลาด นอกจากการตรวจับ Error แล้ว ในบางครั้งถ้าเราตรวจพบความผิดพลาดบางอย่าง เราอาจจะ Throw Exception ขึ้นมาเองก็ได้ เพื่อให้โปรแกรมหยุดการทำงานจนกว่าจะแก้ไขข้อผิดพลาดเรียบร้อยเสียก่อน สำหรับผู้ที่สนใจศึกษาการใช้งาน Try Catch ในภาษา PHP ผมอยากแนะนำให้อ่านบทความนี้ครับ มีชื่อว่า "PHP Try Catch Guide" ของ Mr.Tole ซึ่งจะเขียนแนะนำการใช้งานไว้ค่อนข้างละเอียด มีทั้งแบบ Basic และแบบ Advance ก็ลองอ่านดูแล้วกันนะครับ
แหล่งที่มา: http://phptrycatch.blogspot.com/
RESTful services with jQuery, PHP and the Slim Framework
สำหรับอันนี้เป็นบทความเกี่ยวกับการใช้ Slim Framework ในการพัฒนา RESTful services เขียนโดย Christophe ซึ่งเค้าบอกว่าก่อนที่จะเริ่มพัฒนา มี Framework ตัวเลือกอื่นๆที่น่าสนใจ อย่างเช่น Epiphany, Tonic, Recess และ Frapi ก่อนจะมาจบที่ Slim
Christophe พูดถึงเหตุผลหลักที่เค้าตัดสินใจเลือกใช้ Slimไว้ดังนี้
- Very Lightness and focused on REST and nothing else.
- It supports all HTTP methods (GET, POST, PUT, DELETE) which was key requirement for my Application
แหล่งที่มา: http://coenraets.org/blog
backbone.js - Change Box Color using Backbone Model
ตัวอย่างการควบคุมการเปลี่ยนสีของ div#box ด้วย Backbone Model |
สำหรับตัวอย่างต่อไปนี้จะเป็นการทดลองการประยุกต์ใช้ Backbone Model มาควบคุมการเปลี่ยนสีของ Box (ซึ่งในที่นี้เราจะใช้ div#box โดยกำหนด style ให้มีขนาด 300 x 300 pixel และมี outline:1px solid black) สำหรับการเปลี่ยนสี เราจะทำผ่าน link ที่อยู่ด้านล่าง (เมื่อเรา click ที่ link แต่ละอัน div#box ก็จะเปลี่ยนสีตาม link ที่เรา click)
ในตัวอย่างนี้ div#box จะทำหน้าที่เป็นตัวแทนของ User Interface ซึ่งการเปลี่ยนแปลงของ div#box ที่จะแสดงในตัวอย่างต่อไปนี้ จะทำผ่าน Model ทั้งหมด เมื่อ Model มีการเปลี่ยนแปลง ก็จะส่งผลให้ div#box เปลี่ยนตามไปด้วย เดี๋ยวลองมาดู Code ในส่วนของ JavaScript กันก่อนนะครับ
จาก Code ตัวอย่างข้างต้น มีการประกาศ Box Model โดย extend มาจาก Backbone.Model สังเกตุในส่วนของ initialize เราจะทำการ binding change event เอาไว้ สำหรับในกรณีที่ color มีการเปลี่ยนแปลง เราก็จะทำการเปลี่ยนสีของ div#box ตาม จากนั้นเราก็มีการสร้าง instance ของ Box Model ขึ้นมา โดยกำหนดให้มีค่าสีเริ่มต้นเป็นสีขาว (#fff) บรรทัดต่อมาเป็น Code ที่เรียกใช้งาน jQuery ในการ assign click Event ให้กับ link ที่อยู่ด้านล่างของ div#box เพื่อทำหน้าที่เปลี่ยน color ใน box model ที่เราสร้างขึ้นมา
สำหรับ Code ในส่วนของ HTML สำหรับตัวอย่างนี้ มีดังต่อไปนี้
HTML ในตัวอย่างประกอบด้วย 2 ส่วน ก็คือ ส่วนแรกจะเป็นการประกาศ div#box ส่วนถัดมาเป็นส่วนของ color menu
สำหรับตัวอย่างนี้ จะสังเกตุว่าเราจะควบคุมการเปลี่ยนแปลงของ div#box ผ่าน Model ทั้งหมด ซึ่งจะทำให้ Code ส่วนใหญ่จะถูกแยกไปอยู่ข้างใน Model ไม่กระจัดกระจายออกมาข้างนอก ทำให้ Code เป็นระเบียบและแก้ไขได้ง่าย
สำหรับตัวอย่างนี้ผมอยากให้ค่อยๆอ่านและทำความเข้าใจ ตัวอย่างนี้ไม่ได้มุ่งเน้นในการนำเสนอในเรื่องของ Coding แต่ต้องการเน้นให้เห็นถึงการนำ Model มาใช้ในการแบ่งส่วนในการทำงานของ Application ซึ่งผมคิดว่าตัวอย่างนี้ไม่มีอะไรที่ซับซ้อน ซึ่งจะช่วยให้เห็นภาพของการนำ Model ไปใช้งานได้ง่ายขึ้นครับ
แหล่งที่มา: http://backbonejs.org
Labels:
backbone.js,
JavaScript Framework,
MVC,
Web Development
backbone.js - Binding Custom Named Event to an Object
backbone.js จะช่วยให้เราสามารถ Binding Custom Event เข้ากับ Object ได้ง่ายๆ ด้วยวิธีดังต่อไปนี้
จากในตัวอย่างข้างต้น จะเห็นว่าเราได้ถ่ายทอดความสามารถของ Backbone.Events ให้กับ obj โดยการใช้ method ที่ชื่อว่า extend จาก underscore.js ทำให้ขณะนี้ obj สามารถรองรับการ Trigger และ Binding Custom Named Events ซึ่งในตัวอย่างข้างต้น เราได้ทดลอง Binding Custom Event ที่ชื่อว่า "alert" โดย bind เข้ากับ callback function ที่จะทำหน้าที่แสดง alert message ขึ้นมาเมื่อเกิด Event ที่ชื่อว่า "alert" จากนั้นเราได้เรียก method ที่ชื่อว่า trigger() ของ obj เพื่อทดลองสร้าง event ที่ชื่อว่า "alert" โดยมีการส่ง parameter เป็นชนิด String คำว่า "Hello" ไปด้วย ซึ่งจะส่งผลให้เกิด Alert Message ที่มีคำว่า "Hello" แสดงขึ้นบนหน้าจอ
สำหรับ method ที่ชื่อว่า on นั้น เรายังสามารถส่งค่า parameter ตัวที่สาม ซึ่งจะใช้เป็นค่า Context สำหรับ this ยกตัวอย่างเช่น obj.on("alert", this.render, this) ส่วนการ unbind Event นั้น เราใช้ method ที่มีชื่อว่า off โดยการส่งค่า paremeter ทุกอย่างเหมือนกับตอน binding ทุกประการ อย่างเช่น obj.off("alert", this.render, this)
แหล่งที่มา: http://backbonejs.org
จากในตัวอย่างข้างต้น จะเห็นว่าเราได้ถ่ายทอดความสามารถของ Backbone.Events ให้กับ obj โดยการใช้ method ที่ชื่อว่า extend จาก underscore.js ทำให้ขณะนี้ obj สามารถรองรับการ Trigger และ Binding Custom Named Events ซึ่งในตัวอย่างข้างต้น เราได้ทดลอง Binding Custom Event ที่ชื่อว่า "alert" โดย bind เข้ากับ callback function ที่จะทำหน้าที่แสดง alert message ขึ้นมาเมื่อเกิด Event ที่ชื่อว่า "alert" จากนั้นเราได้เรียก method ที่ชื่อว่า trigger() ของ obj เพื่อทดลองสร้าง event ที่ชื่อว่า "alert" โดยมีการส่ง parameter เป็นชนิด String คำว่า "Hello" ไปด้วย ซึ่งจะส่งผลให้เกิด Alert Message ที่มีคำว่า "Hello" แสดงขึ้นบนหน้าจอ
สำหรับ method ที่ชื่อว่า on นั้น เรายังสามารถส่งค่า parameter ตัวที่สาม ซึ่งจะใช้เป็นค่า Context สำหรับ this ยกตัวอย่างเช่น obj.on("alert", this.render, this) ส่วนการ unbind Event นั้น เราใช้ method ที่มีชื่อว่า off โดยการส่งค่า paremeter ทุกอย่างเหมือนกับตอน binding ทุกประการ อย่างเช่น obj.off("alert", this.render, this)
แหล่งที่มา: http://backbonejs.org
Labels:
backbone.js,
JavaScript Framework,
MVC,
Web Development
Sunday, 15 July 2012
Python - Inheritance
ม้า Pegasus ในตำนานของเทพนิยายกรีก |
จากภาพม้า Pegasus ในรูป เราจะเห็นว่า ม้า Pegasus ไม่ใช่ม้าธรรมดา แต่เป็นม้าพิเศษที่บินได้ สำหรับในแง่ของ OOP เราจะมองว่าม้า Pegasus inherit มาจาก "ม้า" และเพิ่มความสามารถในการ "บิน" เข้าไป เดี๋ยวเราจะมาลองสร้างม้า Pegasus แบบ OOP ในภาษา Python ดูนะครับ
จากตัวอย่างข้างต้น class ที่ชื่อว่า Pegasus จะ inherit มาจาก class ที่ชื่อว่า Horse ทำให้ Pegasus จะได้รับคุณสมบัติจาก Horse ซึ่งในที่นี้ก็คือ method ที่ชื่อว่า run() นอกจากนั้นใน class Pegasus ยังเพิ่มความสามารถ โดยการเพิ่ม method ที่ชื่อว่า fly() เข้าไป ทำให้ Pegasus สามารถเรียกใช้ run() และ fly() ได้
Python - Using Class
Class เป็น Data Structure ประเภทหนึ่ง ซึ่งภายในอาจจะมี Procedure (บางครั้งเรียกว่า Method) และ Data (บางครั้งเรียกว่า Attribute) อยู่ภายใน ปกติเราจะใช้งาน Class เพื่อซ่อนการใช้งานในส่วนที่ซับซ้อนไว้ภายใน โดยจะ provide เฉพาะ methods หรือ attributes ส่วนที่จำเป็นต่อการใช้งานออกสู่ภายนอก สำหรับการใช้งาน Class ใน Python จะสามารถทำได้ดังตัวอย่างต่อไปนี้
สังเกตุว่า Constructor ใน Python จะใช้ method ที่มีชื่อว่า __init__ และทุกๆ method ใน Class เราจะต้องส่ง self เป็น parameter ตัวแรกเสมอ ซึ่งทำให้รู้สึกแปลกๆเหมือนกัน เพราะในภาษาอื่นๆ (เท่าที่เคยใช้มา) เราไม่จำเป็นต้องส่งเข้าไปเอง ยกตัวอย่างอย่างเช่นในภาษา Java เราจะสามารถใช้งาน this ได้เลย ซึ่งในกรณีนี้น่าเป็นเพราะว่า Python ต้องการให้มีความชัดเจนว่าตัวแปรที่นำมาใช้ มีที่มาที่ไปยังไง ตามหลักการที่ว่า explicit is better than implicit (แต่สุดท้ายก็ยังขัดๆอยู่ดี)
Python - Dictionary
ข้อมูลประเภท Dictionary ใน Python มีไว้สำหรับเก็บข้อมูลประเภท Key, Value เราสามารถประกาศตัวแปรประเภท Dictionary ได้โดยใช้เครื่องหมาย {} สำหรับการใช้งาน Dictionary ใน Python สามารถทำได้ตามตัวอย่างดังต่อไปนี้
จากในตัวอย่าง จะสังเกตุว่า นอกจากข้อมูลพื้นฐานทั่วไป Dictionary ยังสามารถเก็บ Function Reference ได้อีกด้วย (เหมือนกับในภาษา JavaScript)
jQuery Transit - Super-smooth CSS3 transformations and transitions for jQuery
jQuery Transit คือ jQuery Plugin สำหรับช่วยในการทำ Animation โดยอาศัยเทคโนโลยี Transformation และ Transition ใน CSS3 พัฒนาโดย Rico Sta. Cruz ซึ่งสามารถใช้งานได้ใน Browser ที่รองรับ อย่างเช่น Firefox 4+, Safari 5+, Chrome 10+, Opera 11+ และ IE10+ สำหรับผู้ที่สนใจ สามารถศึกษาวิธีการใช้งานได้ที่นี่ครับ http://ricostacruz.com/jquery.transit/
แหล่งที่มา: http://ricostacruz.com/jquery.transit
Labels:
Javascript,
jQuery,
jQuery Plugins,
Web Design,
Web Development
PEAR - PHP Extension and Application Repository
ผมชอบนิยามของคำว่า PEAR จากหนังสือเกี่ยวกับ PHP เล่มหนึ่ง เขียนเอาไว้ว่า "PEAR is a fruit of Open Source Community" ซึ่งเป็นข้อความเพียงสั้นๆแต่ได้ใจความ ไม่ต้องอธิบายอะไรมาก PEAR (PHP Extension and Application Repository) เป็น Repository ที่รวบรวม Open Source Library สำหรับ PHP โดยส่วนมากมักจะสับสนกับอีก Project หนึ่งที่คล้ายกัน (แต่ไม่เหมือนกัน) ที่มีชื่อว่า PECL (Pear Extension Community Library) ซึ่งเป็น Project ที่แยกออกมาต่างหากจาก PEAR โดยมีวัตถุประสงค์เพื่อ distribute PHP extensions ที่อยู่ในรูปแบบของ Compiled Code ที่เขียนขึ้นจากภาษา C อย่างเช่น PDO Library ซึ่งถึงแม้จะเป็นคนละ Project กัน แต่เราก็สามารถติดตั้ง PECL Library ผ่าน PEAR ได้โดยใช้คำสั่ง pecl
PHP Distribution ในเวอร์ชั่นหลังๆจะมาพร้อมกับ PEAR Installation Tools เรียบร้อยแล้ว ที่เหลือก็เพียงแค่ทำการติดตั้ง เมื่อติดตั้งเรียบร้อยเราก็จะสามารถใช้งาน PEAR Package Manager ในการติดตั้ง Package ใหม่ๆเข้าไปในระบบ สำหรับวิธีการติดตั้ง PEAR Installation Tools สามารถดูได้ที่นี่ครับ http://pear.php.net/manual/en/installation.getting.php ส่วนวิธีการใช้งาน PEAR Package Manager ในการติดตั้ง Package สามารถดูได้ที่นี่ครับ http://pear.php.net/manual/en/guide.users.commandline.installing.php
แหล่งที่มา: http://pear.php.net
Python - PyPi The Python Package Index
Python Package Index (หรือเรียกสั้นๆว่า PyPi) เป็น repository ที่รวบรวม Package ต่างๆที่ Developer ทั่วโลกพัฒนาไว้และนำมาแบ่งปัน ซึ่งเราสามารถเข้าไป Download และติดตั้งใช้งานได้ ปัจจุบันมีจำนวนทั้งสิ้น 22,474 Packages สำหรับวิธีการติดตั้งสามารถทำได้หลายวิธี ไม่ว่าจะเป็นการใช้ setup script หรือติดตั้งผ่าน easy_install สำหรับผู้ที่สนใจ สามารถเข้าไปดูข้อมูลได้ที่นี่ครับ http://pypi.python.org
แหล่งที่มา: http://pypi.python.org
Python - Easy Install
ตัวอย่างการใช้ easy_install ในการติดตั้ง package networkx |
แหล่งที่มา: http://peak.telecommunity.com
PHP - Checking for Empty String Values
PHP Developer หลายคนมักใช้ empty() function ในการตรวจสอบว่า String เป็นค่าว่างหรือไม่ ซึ่งเป็นวิธีที่ไม่ค่อยจะถูกต้องนัก เพราะว่า empty() จะคืนค่ากลับมาเป็น true ในกรณีที่ String มีค่าเท่ากับ "0" (เพราะ PHP จะตีความว่า 0 มีค่าเท่ากับ false) สำหรับการตรวจสอบ String ที่ถูกต้อง ควรใช้วิธีการดังต่อไปนี้
แหล่งที่มา: หนังสือ PHP Programming Solution (McGraw Hill) เขียนโดย Vikram Vaswani
แหล่งที่มา: หนังสือ PHP Programming Solution (McGraw Hill) เขียนโดย Vikram Vaswani
cssreset.com - most popular CSS Reset scripts, all in one place
สำหรับคนที่พัฒนา Web น่าจะคุ้นเคยกับปัญหา Default Style ของแต่ละ Browser ที่ไม่ค่อยจะเหมือนกัน สำหรับวิธีการที่จะใช้ในการแก้ปัญหาก็คือการใช้ CSS Reset เพื่อปรับ Style เริ่มต้นของแต่ละ Browser ให้ใกล้เคียงกันมากที่สุดก่อน ที่ www.cssreset.com จะนำ CSS Reset ที่เป็นที่นิยมมารวมไว้ให้เราได้เลือกใช้งาน โดยมีทั้งของ Eric Meyer, HTML5 Doctor, Yahoo! เป็นต้น สำหรับผู้ที่สนใจใช้งานสามารถเข้าไปที่ http://www.cssreset.com/
แหล่งที่มา: http://www.cssreset.com
34 cheat sheets for web designers and developers
อันนี้ไปเจอมาระหว่างหาข้อมูลครับ เห็นว่ามีประโยชน์ดีเลยอยากเอามาแนะนำไว้ครับ เป็น Cheat Sheets สำหรับ Web Designers และ Developers ก็มีหลากหลาย มีทั้ง WordPress , PHP , jQuery , HTML, CSS, Flash, Photoshop, Illustrator, Firework, Indesign, RGB Color Code ครับ ลองเลือกดูเอาเองแล้วกันนะครับ สำหรับผู้ที่สนใจสามารถเข้าไป download ได้ที่นี่ครับ http://www.webanddesigners.com/34-cheat-sheets-for-web-designers-and-developers/
แหล่งที่มา: http://www.webanddesigners.com
Labels:
Cheat Sheet,
References,
Web Design,
Web Development
URL Rewriting using mod_rewrite
การนำ mod_rewrite มาช่วยในการแปลง URL นอกจากจะทำให้ได้ URL ที่ดูสวยงามแล้ว ยังช่วยให้ Application ของเราปลอดภัยจากการที่ URL โดนเปลี่ยนแปลง และยังช่วยในเรื่องของ SEO ได้ด้วย mod_rewrite จะทำหน้าที่แปลง URL ที่ User Request ให้เห็น URL ตามที่เรากำหนด มักจะใช้ในการแปลง URL ในรูปแบบที่่ซับซ้อนให้มีรูปแบบที่ง่ายขึ้น ยกตัวอย่างเช่น สมมุติว่า URL จริงเป็นดังต่อไปนี้
http://www.mysite.com/complicated/and/way/too/long/url/here
เราสามารถเปลี่ยนให้เป็นรูปแบบที่ง่ายขึ้น ดังนี้
http://www.mysite.com/shortcut
ซึ่งใน htppd.conf (หรือใน .htaccess) เราจะ config mod_rewrite ดังต่อไปนี้
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^/shortcut$ /complicated/and/way/too/long/url/here
</IfModule>
สำหรับวิธีการกำหนด RewriteRule จะเป็นไปตาม Syntax ดังต่อไปนี้
RewriteRule Pattern Substitution [Flag(s)]
ในส่วนของ Pattern นั้น เราจะใช้ในการกำหนดรูปแบบของ URL ที่เราต้องการเปลี่ยนแปลง โดยใช้ Regular Expression ในส่วนของ Substitution เราจะใช้ในการแทนค่า URL (ซึ่งเมื่อผ่านการแทนค่าเรียบร้อยแล้ว ก็จะคือ URL จริงที่ Apache จะนำไปใช้นั่นเอง) ส่วน Flags มีไว้สำหรับกำหนด Options พิเศษอื่นๆ เดี๋ยวเราจะลองมาดูตัวอย่างที่ซับซ้อนขึ้นมาอีกหน่อย
RewriteRule /products/([0-9]+) /siteengine/products.php?id=$1
ให้สังเกตุว่า ในส่วนของ Substitution เรามีการใช้งาน $1 ซึ่งมีความหมายว่า ให้แทนที่โดยใช้ค่าจาก Sub Pattern ชุดที่ 1 (Pattern ที่อยู่ในวงเล็บ เราจะเรียกว่า Sub Pattern) ในกรณีที่มี Sub Pattern มากกว่า 1 ชุด การแทนที่ เราจะใช้ $1 ,$2, $3 ไปเรื่อยๆ ตามลำดับ จาก Rule ในตัวอย่างข้างต้น จะทำให้ URL สามารถเรียกใช้งาน URL ในรูปแบบดังต่อไปนี้
http://www.mysite.com/products/26
ซึ่งเมื่อผ่าน Rewrite Engine ก็จะถูก rewrite ให้เป็น URL ดังต่อไปนี้
http://www.mysite.com/siteengine/products.php?id=26
สำหรับ URL ที่ไม่ตรงตาม Pattern ที่กำหนดไว้ใน RewriteRule จะไม่สามารถเรียกใช้งาน Script ของเราได้ ซึ่ง Apache จะส่งค่า HTTP Status กลับคืนเป็น 404 Not Found แทน ซึ่งจะทำให้เรามั่นใจได้ว่า URL ที่ Request มาถึง Script ของเราได้ จะต้องเป็น URL ที่ถูกต้องตามรูปแบบที่เรากำหนดไว้เท่านั้น
เราสามารถกำหนด RewriteRule ได้มากกว่า 1 Rule ดังต่อไปนี้
RewriteRule ^/products$ /content.php
RewriteRule ^/products/([0-9]+)$ /content.php?id=$1
ซึ่งในกรณีที่มี RewriteRule มากกว่าหนึ่ง RewriteEngine จะทำการตรวจสอบ Pattern ในแบบ Top Down (บนลงล่าง) และในกรณีที่เจอ Pattern ที่ตรงกับ URL ที่ Request ก็จะหยุดทันที ดังนั้นเราควรกำหนด URL ที่เป็น Generic (บางครั้งเรียกว่า Catch All URL) เอาไว้สุดท้าย
สำหรับ Parameter ตัวสุดท้ายที่ชื่อว่า Flag มีไว้สำหรับส่ง Response Header ในกรณีที่ URL ที่ Request ตรงกับ Pattern ที่กำหนด อย่างเช่น
'forbidden' หรือ 'f' เอาไว้สำหรับส่ง 403 Forbidden
'gone' หรือ 'g' เอาไว้สำหรับส่ง 410 Gone
นอกจากนั้น เรายังใช้ Flag ในการสั่ง Redirection และกำหนด MIME-Type ได้อีกด้วย สำหรับการใช้ Flag ในการกำหนด Option กรณีอื่นๆ อย่างเช่น
'nocase' หรือ 'NC' ใช้สำหรับกำหนดให้ Pattern เป็นแบบ Case Insensitive
สำหรับส่วนต่อไป เราจะมาดูวิธีการใช้งาน Rewrite Condition กันนะครับ สำหรับ Syntax การใช้งาน Rewrite Condition จะเป็นดังต่อไปนี้
RewriteCond Something_to_test Condition
ก่อนอื่นต้องเข้าใจกระบวนการทำงานของ Rewrite Engine กันก่อน ดังนี้ mod_rewrite จะเริ่มจากการตรวจสอบ URL ก่อน ว่าตรงกับ Pattern ที่กำหนดไว้ใน RewriteRule หรือเปล่า ซึ่งถ้าหากตรง ก็จะตรวจสอบต่อไปว่า มี RewriteCondition กำหนดไว้สำหรับ Rule ดังกล่าวหรือเปล่า ซึ่งถ้ามีก็จะทำการทดสอบ Condition ตามเงื่อนไขที่กำหนด ซึ่งถ้าทดสอบเงื่อนไขแล้วคืนค่ากลับมาเป็น True ก็จะทำกระบวนการ Substitution ตามที่กำหนดไว้ใน RewriteRule สำหรับในกรณีที่ทดสอบเงื่อนไขแล้วคืนค่ากลับมาเป็น False ก็จะทำการทดสอบเงื่อนไขต่อไป (ถ้ามี)
ด้วยความสามารถในการทดสอบ Condition ดังกล่าว ทำให้เราสามารถ Customize URL Rewriting ตามตัวแปร HTTP Variable ใดๆก็ตามที่เราได้รับจาก Apache สำหรับตัวอย่างของ HTTP Variable ที่สามารถใช้งานได้ มีดังต่อไปนี้ (นำมาแสดงเป็นตัวอย่างเพียงแค่บางส่วน)
HTTP_USER_AGENT, HTTP_REFERER, HTTP_COOKIE, HTTP_HOST, HTTP_ACCEPT, REMOTE_ADDR, REMOTE_HOST, REQUEST_METHOD, SERVER_NAME, SERVER_ADDR, SERVER_PORT, SERVER_PROTOCOL ...
ต่อไปลองมาดูตัวอย่างการใช้งาน RewriteCondition คู่กับ RewriteRule ดังต่อไปนี้ครับ
RewriteCond %{HTTP_USER_AGENT} ^Mozilla.*
RewriteRule ^/$ /homepage.max.html [L]
RewriteCond %{HTTP_USER_AGENT} ^Lynx.*
RewriteRule ^/$ /homepage.min.html [L]
RewriteRule ^/$ /homepage.std.html [L]
เมื่อ User ทำการ Request มาที่ http://www.mysite.com/ จะเกิดการทำงานดังต่อไปนี้
User ที่ใช้ Mozilla Browser จะถูกพาไปที่ homepage.max.html
User ที่ใช้ Lynx (Text Based Browser) จะถูกพาไปที่ homepage.min.html
User ที่ใช้ Browser อื่นๆ จะถูกพาไปที่ homepage.std.html
เราสามารถนำ mod_rewrite มาประยุกต์ใช้ในการป้องกันการเรียกใช้งาน image จาก Web ภายนอก ได้ โดยกำหนด config ดังนี้
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://localhost/.*$ [OR,NC]
RewriteCond %{HTTP_REFERER} !^http://mysite.com/.*$ [OR,NC]
RewriteCond %{HTTP_REFERER} !^http://www.mysite.com/.*$ [OR,NC]
RewriteRule .*\.(gif|GIF|jpg|JPG)$ http://mysite/images/bad.gif [L,R]
สำหรับผู้ที่สนใจ สามารถศึกษาเพิ่มเติมจาก Official Document ของ Apache ได้ที่นี่ครับ http://httpd.apache.org/docs/current/mod/mod_rewrite.html ส่วน Guide Line ในการใช้งานในรูปแบบต่างๆ สามารถดูได้ที่นี่ครับ http://httpd.apache.org/docs/2.0/misc/rewriteguide.html
แหล่งที่มา:
Labels:
Apache,
mod_rewrite,
SEO,
URL Rewrite,
Web Development
Saturday, 14 July 2012
How To Add Animated Flying Twitter Bird Widget
คิดว่าหลายๆคนน่าจะพอคุ้นเคยกับปุ่ม Twitter Follow Me แต่สำหรับอันนี้เป็นปุ่ม Twitter Follow Me แบบพิเศษ คือเป็นนกบินได้ มันจะบินตามเราไปเวลาที่เราเลื่อน Scroll ของ Page ขึ้นและลง สำหรับใครที่สนใจนำไปใช้ ให้เข้าไปที่ http://www.way2blogging.org/2011/01/how-to-add-animated-flying-twitter-bird.html บนหน้า Web จะมีปุ่มให้เราสามารถ Generate Script เพื่อที่เราจะสามาถนำไปแปะเอาไว้บน Web ของเราได้ครับ
แหล่งที่มา: http://www.way2blogging.org
Labels:
Javascript,
Javascript Library,
Twitter,
Web Design,
Web Development
Subscribe to:
Posts (Atom)