Quantcast
Channel: cc :: somkiat
Viewing all 2000 articles
Browse latest View live

Continuous Integration และ Testing ควรอยู่ด้วยกันเสมอ

$
0
0

ci-testing-00

ci-testing-00 ในการพัฒนา software ได้นำเอาแนวคิด Continuous Integration(CI) เข้ามาใช้งาน ซึ่งผมคิดว่าเป็นสิ่งที่ขาดไม่ได้เลย เพื่อช่วยทำให้ทีมทำการ integrate บ่อย ๆ เพื่อช่วยทำให้ software ที่สร้างค่อย ๆ เติบโตอย่างยั่งยืน เพื่อช่วยทำให้ทีมได้รับ feedback กลับมาอย่างรวดเร็วทั้งดีและร้าย เพื่อจะได้แก้ไขและปรับปรุงได้อย่างทันท่วงที
แต่สิ่งที่น่าแปลกใจก็คือ ไม่นำการทดสอบ (Testing) เข้ามาร่วมทำงานกับ Continuous Integration !!

ทีมที่มีการนำแนวคิด Continuous Integration มาใช้นั้น

จะเริ่มจากการสร้างระบบ Continuous Integration Server ทำหน้าที่ build, package และ deploy/release ระบบงาน ส่วนการทดสอบยังคงทำแบบเดิม หรือ แบบ manual !! ถ้าถามว่ามันมีข้อดีไหม ? ตอบได้เลยว่ามีข้อดีมาก เช่น
  • ทำให้ทีมพัฒนารู้ว่า source code สามารถ compile ได้หรือไม่
  • ทำให้ทีมพัฒนารู้ว่า source code ทั้งหมดยังคงทำได้ได้ ไม่มีปัญหา
  • ทำให้สามารถ deploy ไปยัง server ต่าง ๆ ได้อย่างรวดเร็ว โดยไม่ต้องใช้คน
ดังนั้นเรื่องของ source code จะเป็น version ล่าสุดเสมอ เรื่องของกระบวนการ build->deploy->release เร็วและสะดวกขึ้น
แต่ปัญหาที่ตามมาคือ เรื่องของคุณภาพของระบบ !!
เนื่องจากในแต่ละการ build/deploy นั้น ไม่มีชุดการทดสอบแบบอัตโนมัติอะไรเลย หรือไม่มีกระบวนการทดสอบเข้ามาอยู่ในระบบ Continuous Integration ซึ่งก่อให้เกิดปัญหาตามมามากมายเช่น
  • ทีมพัฒนาไม่ทำการทดสอบทั้งระบบ
  • ทีมทดสอบทำการทดสอบไม่ไหว
  • ทีมทดสอบทำการทดสอบช้า
  • ทีมทดสอบไม่ทดสอบทุก ๆ test case
  • ทีมพัฒนาและทีมทดสอบไม่ทำการ regression test
ลองคิดดูสิว่า ถ้าต้อง deploy ระบบงานไปในแต่ละ environment ทั้ง Dev, Test, SIT, SUT, UAT, Staging, Production จะต้องทำการทดสอบกันอย่างไร ?
ปัญหาเหล่านี้มันสะท้อนถึงโครงสร้างและกระบวนการขององค์กร ดังนั้นสิ่งที่ต้องแก้ไขทีคือ ต้องนำเอาการทดสอบเข้ามาอยู่ใน Continuous Integration ด้วยเสมอ โดยการทดสอบควรที่จะทำงานแบบอัตโนมัติอีกด้วย (Automated Testing)

โดยในระบบ Continuous Integration ควรมีความสามารถดังนี้ เพื่อทำให้การทดสอบมีประสิทธิภาพ

  • Scalability สามารถทำการทดสอบทุก ๆ test case ได้ทุกครั้งเมื่อ source code เปลี่ยนแปลง
  • Automation สามารถทำการทดสอบได้แบบอัตโนมัติ เมื่อเกิดปัญหาระบบจะหยุดทำงาน และแจ้งปัญหาออกมา
  • Parallel testing เมื่อจำนวนของชุดการทดสอบเยอะขึ้น ดังนั้นระบบควรทำการทดสอบแบบขนานได้ เพื่อเพิ่มความเร็วของการทดสอบ

คำถามสำหรับทีมพัฒนาคือ

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

สวัสดี .Net Core สิ่งที่นักพัฒนาต้องลอง

$
0
0

net-00

net-00 บริษัท Microsoft ได้เปิดตัว .Net Core ออกมา เป็นการเปลี่ยนแปลงของ Microsoft ที่น่าสนใจอย่างมาก ซึ่งทำให้นักพัฒนาสามารถพัฒนาระบบงาน ด้วยภาษา C# และ F# รวมไปถึง ASP.Net บนระบบปฏิบัติใดก็ได้ ทั้ง Windows, Linux และ Mac ยังไม่พอนะ มี Image สำหรับ Docker มาให้ใช้งานอีกด้วย ซึ่งถือได้ว่ามีประโยชน์มาก ๆ ต่อนักพัฒนา ดังนั้นนักพัฒนาลองมาใช้งานกันดีกว่า

Software สำหรับการทดลองใช้งานประกอบไปด้วย

  • Mac OS X
  • Docker for Mac
  • NPM (Node Package Manager)
  • .Net Core
โดยการทดลองใช้งานผมทำผ่าน Docker นะ สามารถทำตาม web ได้เลย คือ [code] $docker run -it microsoft/dotnet:latest $mkdir hwapp $cd hwapp $dotnet new $dotnet restore $dotnet run [/code] ผลการทดลองเป็นดังนี้ net-01 จะเห็นว่าใช้งานไม่ยากเลยนะ จากนั้นมาดูขนาดของ image ของ Microsoft .Net หน่อยว่ามีขนาดเท่าไร พบว่ามีขนาด 548.6 MB ซึ่งมีขนาดใหญ่พอสมควรแต่รับได้นะ !! จากนั้นลองมาสร้างระบบงานจริง ๆ กันดีกว่า แนะนำให้ไปอ่านเอกสารจาก ASP.NET Core Documentation เนื่องจากมีให้ครบเลย ดังนั้นมาลองสร้างระบบงานง่าย ๆ มาลองกันดีกว่า 1. เริ่มต้นสร้าง project ด้วย Yeoman เพื่อความง่ายสำหรับการสร้าง project ทาง Microsoft ได้เตรียม template ของ Visual Studio Project ไว้ให้ ซึ่งสามารถใช้งานผ่าน Yeoman ช่วยสร้าง project ขึ้นมาแบบง่าย ๆ แต่ต้องทำการติดตั้ง NPM ก่อนนะ จากนั้นก็ติดตั้งดังนี้ [code] $npm install -g yo bower grunt-cli gulp $npm install -g generator-aspnet [/code] 2. เมื่อติดตั้งทุกอย่างเรียบร้อยก็สร้าง project กัน ทำการสร้าง project ด้วยคำสั่ง [code] $yo aspnet [/code] จะมี project ให้เลือกเยอะเลยทั้ง
  • Web application
  • Console application
  • Web API application
  • Class library
  • Unit test project (xUnit.net) ซึ่งชอบมาก ๆ
โดยในตัวอย่างนี้ผมเลือก Web API application แสดงดังรูป net-02 จากนั้นทำการตั้งชื่อ project ซะ แล้ว Yeoman จะทำการสร้าง project เริ่มต้นให้ดังรูป แถมอธิบายขั้นตอนการ run ให้พร้อม net-03 จากนั้นทำการเปิด code ขึ้นมาดูหน่อย ซึ่งผมใช้ Visual Studio Code แสดงดังนี้ net-04 สำหรับคนที่ติดตั้ง .Net Core ไว้ที่เครื่อง สามารถทำการทดสอบ run ได้ดังนี้ [code] $dotnet restore $dotnet build $dotnet run [/code] จากนั้นก็ทดสอบใช้งานผ่าน browser ด้วย url http://localhost:5000/api/values ผลการทำงานเป็นดังนี้ net-05 เท่านี้ก็ใช้งานได้แล้ว ง่ายไหมล่ะ !! ยังไม่พอนะ พอดีไปเห็นใน project พบว่ามีไฟล์ Dockerfile มาให้ด้วย ดังนั้นสามารถ run บน Docker ได้อีกด้วย มาลองใช้งานกันดีกว่า [code] $docker build -t api . $docker run -it -p 5000:5000 --rm --name api api [/code] เพียงเท่านี้ก็ใช้งานผ่าน Docker ได้เลย เป็นวิธีการที่ง่าย ๆ มาก ซึ่ง Developer ทุกคนสามารถใช้งานได้เลย รออะไรอยู่ ไปลองใช้งานกันเลยครับ

เมื่อ Comment ใน code ไม่ใช่เรื่องเล่น ๆ !!

$
0
0

comment-00

comment-00 จากคำถามใน Quora.com เรื่อง What is the best comment in source code that you have ever encountered ? ว่าด้วยเรื่องการ comment ใน source code ที่ดี มันเป็นคำถามที่ดีมาก ๆ รวมทั้งคำตอบต่าง ๆ ก็น่าสนใจ แต่ก็มีบางคำตอบที่ฮา ๆ เยอะเช่นกัน มาดูกันหน่อยสิ

เริ่มด้วย comment ที่เหมือนจะฮา แต่คิดว่าไม่ฮา !!

code เหล่านี้ต้องไม่เคยผ่านการทำ code review แน่ ๆ บริษัทที่จ้าง developer คนนี้ไม่น่าจะพอใจนะ [code] The company pays no bonus - forget about it dude. Don't come! I'm ready to leave! This project contains huge amount of bugs. You won't stay long! Bye! Best luck! [/code] comment-01 ถ้าเจอ code แบบนี้ไม่น่าจะชอบกันนะ !! [code] IF TIMEDIFF >=5 SAY "THE SYSTEM IS FUCKED, PLEASE BEAR WITH US" SLEEP(10) ENDIF [/code] ถ้าเจอแบบนี้จะกล้าแก้ไขไหม ? [code] //When I wrote this, only God and I understood what I was doing //Now, God only knows /* You are not expected to understand this */ // // Dear maintainer: // // Once you are done trying to 'optimize' this routine, // and have realized what a terrible mistake that was, // please increment the following counter as a warning // to the next guy: // // total_hours_wasted_here = 42 // [/code] ถ้าเจอ comment แบบนี้ ก็เอาที่สบายใจกันนะ [code] if (counts < 0xFF567812 ) // Programmer1 - WTF is this magic number bullshit // Programmer2 - I have no fucking clue. I've been trying to figure it out for years. // Programmer1 - We should figure this out and comment it // Programmer3 - Did we ever figure this out? // Programmer2 - No [/code] หรือเจอ code แบบนี้จะทำการ comment หรือปรับปรุงกันดีนะ ? comment-06 ขยันกันไปถึงไหนนะ สำหรับการเขียน comment [gist id="9f28126836bf265523d08bed1183acad" file="01.txt"]

กลุ่มต่อมาคือสร้างสรรค์มาก ๆ

สงสัยว่า Developer น่าจะมีเวลาว่างกันมาก ๆ ตัวอย่างที่น่าสนใจมาก ๆ คือ Just Crawl It ของ NIKE comment-03 ต่อมาคือ พยายามสูงมาก ๆ comment-04 Geek เท่านั้นถึงจะเข้าใจ comment-09 ประกาศจ้างงานกันแบบนี้เลย !! comment-05 อันนี้น่ากลัวมาก ๆ comment-08 ปิดท้ายด้วย comment นี้ล่ะกัน สาธุ !! comment-07
วันนี้ Developer ทำการเขียน comment กันอย่างไรบ้าง ? Developer เป็นคนตลกนะ ว่าไหม ?

พัฒนาระบบ Swift Web Application ด้วย Vapor กัน

$
0
0

Screen Shot 2559-07-03 at 1.01.35 PM

swift-00 ในช่วงวันหยุดมาศึกษาสิ่งใหม่ ๆ กันหน่อย หรือว่าใหม่ของผมแต่อาจจะเก่าของคนอื่นก็ได้ !! สำหรับนักพัฒนา iOS app นั้น ต้องสร้างระบบ Backend/API หรือ Server-side มาใช้งานเสมอ ซึ่งมักจะพัฒนาด้วยภาษาอื่น ๆ เช่น Java, PHP, Node.js, Rail และ Go เป็นต้น ทำให้ต้องเรียนรู้มากขึ้น ทำให้ต้องมีทีมมากขึ้น

คำถามที่น่าสนใจก็คือ

ถ้าระบบในส่วน Server-side และ iOS app นั้น สามารถพัฒนาด้วยภาษาเดียวกัน มันน่าจะดีไม่น้อยนะ ? คำถามนี้ถูกตอบชัดเจนขึ้นเมื่อ Swift เปิด opensource ทำให้สามารถพัฒนาทั้งสองฝั่งด้วยภาษา Swift ซึ่งทำให้เกิด project S4 ขั้นมา โดย S4 ย่อมาจาก Server Side Swift Standard นั่นคือมาตรฐานสำหรับการสร้าง Server Side ด้วยภาษา Swift ประกอบไปด้วยส่วนการทำงานดังนี้
  • Middleware
  • Request
  • Response
  • Server

ทำให้เกิด framework ต่าง ๆ ในภาษา Swift

สำหรับสร้างระบบ web application หรือ server side เยอะมาก ๆ ตัวอย่างเช่น ยังไม่พอนะ ในแต่ละ framework ก็พัฒนาอยู่บน Swift ต่าง version กันอีก ชีวิตดูลำบากมาก ๆ !! แต่ไม่เป็นไรมี Swift Package Manager ให้ใช้งาน

แล้วจะเลือก Framework ตัวไหนดีล่ะ ?

ผมแนะนำให้ลองใช้งานทั้งหมดดูนะครับ ส่วนผมเลือก Vapor เพราะว่าชอบในรูปแบบการใช้งานเท่านั้นเอง แถมมีเอกสารที่ใช้ได้เลย รวมทั้งใช้งานผ่าน command line ได้อีกด้วย มาเริ่มกันดีกว่า Software ที่ใช้งานประกอบไปด้วย
  • Mac OS
  • Xcode 7.3.1

ขั้นตอนที่ 1 ติดตั้ง Swift Package Manager

ใช้สำหรับจัดการ version ของ dependency ที่ใช้งานใน project ช่วยให้สามารถทำการ build และติดตั้ง library ต่าง ๆ แบบอัตโนมัติ ซึ่งเหมือนกับ Cocoapods และ Carthage นั่นเอง
แต่โชคไม่ดีนักที่ Swift 3 ยังอยู่ในสถานะของการพัฒนา ทำให้มี version ต่าง ๆ ออกมามากมาย ดังนั้นจำเป็นต้องใช้งาน Swift Version Manager หรือ Swiftenv
ทำการติดตั้งดังนี้ [gist id="9282ac5859fad000f3386607103a987f" file="install-swift-package-manager.txt"]

ขั้นตอนที่ 2 ติดตั้งภาษา Swift 3

[code] $swiftenv install DEVELOPMENT-SNAPSHOT-2016-05-31-a [/code]

ขั้นตอนที่ 3 สร้าง Swift project

[gist id="9282ac5859fad000f3386607103a987f" file="create-project.txt"] ผลการทำงานเป็นดังนี้ swift-02 ประกอบไปด้วย
  • main.swift คือไฟล์เริ่มต้นการทำงานของระบบ เราจะแก้ไขที่ไฟล์นี้
  • Package.swift คือไฟล์สำหรับจัดการ dependency หรือ library ต่าง ๆ ที่ต้องการใช้งาน

ขั้นตอนที่ 4 ทำการเพิ่ม dependency ของ Vapor ในไฟล์ Package.swift

[gist id="9282ac5859fad000f3386607103a987f" file="Package.swift"]

ขั้นตอนที่ 5 เขียน code ในไฟล์ main.swift กันเถอะ

[gist id="9282ac5859fad000f3386607103a987f" file="main.swift"]

ขั้นตอนที่ 6 ทำการ build และ run project กันเลย

[code] $swift build [/code] ผลการ build เป็นดังนี้ swift-03 [code] $.build/debug/HelloWorld [/code] จากนั้นเข้าใช้งานผ่าน browser ที่ url=http://localhost:8080/ swift-04 และทดสอบ response ในรูปแบบ JSON ดังนี้ http://localhost:8080/json swift-05

ขั้นตอนที่ 7 ทำการ deploy ไปยัง Heroku นิดหน่อย

[gist id="9282ac5859fad000f3386607103a987f" file="deploy-to-heroku.txt"] สามารถเข้าใจงานได้ที่ http://up1-swift-vapor.herokuapp.com/json
เพียงเท่านี้ก็สามารถพัฒนา Server Side ด้วยภาษา Swift ได้แล้วนะ ลองเล่นและใช้งานกันได้ครับ
Code ตัวอย่างอยู่ที่ Github::Up1 Reference Websites https://stormpath.com/blog/tutorial-build-first-swift-web-app-vapor https://github.com/qutheory/vapor-example

ทำไม code แย่ ๆ มันจึงเกิดขึ้นในทุกระบบ !!

$
0
0

poor-code-00

poor-code-00 ทำไมในการพัฒนา software ถึงมี bad code หรือ code ที่มันแย่ ๆ ขึ้นมาเพียบเลย ? หรือว่าจำนวนนักพัฒนาที่สามารถเขียน code ให้มีคุณภาพมีน้อยกันนะ ? หรือว่ามันมีเหตุผลอื่น ๆ อีกนะ ? เราลองมาค้นหาคำตอบกันหน่อยสิ

สิ่งที่มักได้ยินตลอดมาก็คือ

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

ในการพัฒนา software เน้นเพียงทำให้เสร็จ ทำให้เสร็จ ทำให้เสร็จ !!

โดยเรื่องคุณภาพของ code มีสำคัญรองลงไป ทำให้นักพัฒนาสนใจเพียงการทำงานให้เสร็จ ๆ ไป ทำให้นักพัฒนาคิดว่า เขียนอย่างไรก็ได้ เพื่อให้งานเสร็จตามเวลา นั่นหมายความว่า เราเริ่มต้นจากการสร้างของแย่ ๆ และทุก ๆ คนที่เกี่ยวข้องก็เห็นดีเห็นงามไปด้วย ผลลัพธ์ที่ออกมาจึงเป็นอย่างที่เห็นในทุกวันนี้นั่นเอง poor-code-01

ดังนั้นสิ่งที่ควรแก้ไขคือ เรื่องของคุณภาพของ code

มันต้องเป็นสิ่งที่มาพร้อมกับนักพัฒนาตั้งแต่เริ่มต้น เหมือนกับการของแพทย์ คุณจะไว้ใจและยอมรับให้แพทย์ที่ไม่มีมาตรฐานมารักษาหรือผ่าตัดหรืออย่างไร ? แน่นอนว่า คุณย่อมไม่ไว้ใจ เหมือนกับการบิน คุณจะไว้ใจและยอมรับให้นักบินที่ไม่เคยนำเครื่องบินลงอย่างปลอดภัยมาขับหรือไม่ ? แน่นอนว่า คุณย่อมไม่ไว้ใจ ดังนั้นในการพัฒนา software ก็เช่นกัน คุณจะไว้ใจและยอมรับให้มี code แย่ ๆ กันหรือไง ? แน่นอนว่าไม่

คำถามที่น่าสนใจ คือ แล้วทำไมนักพัฒนาถึงสร้าง code แย่ ๆ ออกมาล่ะ ?

สาเหตุเกิดจากอะไรบ้าง ? เมื่อย้อนกลับไปดูที่หนังสือสมัยเรียน Programming ช่วงเริ่มต้น พบว่ามันประกอบไปด้วย code ที่แย่ ๆ จำนวนมาก ตัวอย่างเช่น
  • การตั้งชื่อที่มีแต่ a,b,c,i,j,k,x,y,z
  • การตั้งชื่อ class เช่น Sample1, Class1
  • การทำงานอยู่ใน main method ทั้งหมด
  • ตัวอย่าง code ที่แย่ ๆ เช่นการ validation ข้อมูล และการจัดการ error ต่าง ๆ รวมทั้งการใช้งาน if-else และ switch-case แบบเยอะ ๆ
  • หนังสือส่วนใหญ่เน้นสอนแต่เรื่องของ syntax ของภาษา
ซึ่งหนังสือเหล่านั้นสอนเพียงให้เข้าใจ syntax ของภาษา เน้นเพียงให้ระบบทำงานได้อย่างถูกต้องตามที่ต้องการ แต่ไม่ได้สอนให้เราเขียน code เพื่อให้คนอื่น ๆ อ่านเข้าใจ เน้นเพียงให้เครื่องเข้าใจและทำงานได้อย่างถูกต้อง แน่นอนว่า เป็นสิ่งที่ทำให้นักพัฒนาใหม่ ๆ เดินผิดทาง เป็นสาเหตุหนึ่งที่คนส่วนใหญ่มักบอกว่า นักพัฒนา software มันพูดกับคนอื่นไม่รู้เรื่อง

ดังนั้นหนังสือที่นักพัฒนาทุกคนควรอ่าน เรียนรู้ตั้งแต่เริ่มเขียน code คือ

สิ่งที่นักพัฒนาทุกคนควรใส่ใจ คือ

เรียนรู้การสร้าง code ที่มีคุณภาพที่ดี ทั้งจากการเรียนรู้ด้วยตนเอง ทั้งจากหนังสือต่าง ๆ ทั้งจากการเรียนรู้จากผู้อื่น ทั้งจากการ review code อยู่อย่างสม่ำเสมอ แล้วจะทำให้ code มีคุณภาพสูงขึ้นอย่างต่อเนื่อง
วันนี้คุณสร้าง code แย่ ๆ ออกมามากน้อยเพียงใด ?

Stub Driven Development สำหรับ Mobile Application

$
0
0

stub-00

stub-00 ในการพัฒนา Mobile app ส่วนใหญ่นั้น จำเป็นต้องทำงานร่วมกับ Server-side API ผ่านระบบ network ไม่ว่าจะเป็น RESTful API และ Web Service ปัญหาที่มักเกิดขึ้นเสมอก็คือ
  • ต่างคนต่างทำงาน
  • ต้องรอกันเสมอ
  • ถ้าฝั่ง API พัฒนาไม่เสร็จ ฝั่ง Mobile app ก็ไม่เสร็จเช่นกัน
  • ถ้าระบบ network มีปัญหา หรือ server มีปัญหา จะทำให้การพัฒนาฝั่ง Mobile app สะดุดหรือหยุดชะงักไป
  • ไม่สามารถจำลองเหตุการณ์ที่ต้องการได้เช่น API ทำงานช้า, API ทำงานผิดพลาด เป็นต้น
และปัญหาอื่น ๆ อีกมากมาย ดังนั้นถ้ายังคงทำงานกันแบบนี้น่าจะไม่รอดอย่างแน่นอน คำถามคือ เราจะทำอย่างไรดีล่ะ ? คำตอบมีหลายแนวทางมาก ทั้งจากการวางแผน ทั้งจากขั้นตอนการทำงาน ทั้งจากโครงสร้างของทีม

หนึ่งในวิธีการที่นำมาใช้คือ Stub Driven Development

เป็นหนึ่งในแนวคิดเรื่อง Test-Double ซึ่งประกอบไปด้วย
  • Dummy
  • Stub
  • Spy
  • Mock
  • Fake
โดย Stub นั้นเป็นการจำลองการทำงานของ Server-side API ขึ้นมา เรียกเมื่อใดหรือกี่ครั้งก็ตาม จะได้ข้อมูลเหมือนเดิมตลอด เพื่อทำให้ทางฝั่ง Mobile app สามารถพัฒนาระบบได้ ไม่จำเป็นต้องรอให้ฝั่ง Server-side พัฒนาเสร็จ แต่สิ่งที่ต้องทำก่อนคือ การพูดคุยและสรุปข้อตกลงในการเชื่อมต่อร่วมกัน ประกอบไปด้วย
  • Protocol ที่ใช้เชื่อมต่อ
  • Endpoint สำหรับการเรียกใช้งาน
  • ข้อมูลของ request ว่าเป็นอย่างไรบ้าง
  • ข้อมูลของ reponse ว่าเป็นอย่างไรบ้าง
แนวทางนี้มันจะส่งผลต่อการพัฒนา Mobile app อย่างมาก เช่นเรื่องโครงสร้างของ code ต้องแก้ไข ให้สามารถสลับการทำงานทั้งของจริงและของปลอมได้ง่าย นั่นคือ code จะต้องทดสอบได้ง่าย หรือ Testable code นั่นเอง เป็นเรื่องที่นักพัฒนาทุกคนต้องเรียนรู้ ฝึกฝน และ นำไปใช้งาน

มาดูข้อดีของ Stub Driven Development ว่ามีอะไรบ้าง ?

เริ่มจากทำให้การพัฒนา Mobile app ง่ายขึ้น แต่อาจจะต้องเสียเวลาในช่วงแรกสำหรับการเตรียมข้อมูลของ API ให้เรียบร้อย จากนั้นคุณจะสามารถควบคุมสิ่งต่าง ๆ ได้ง่ายขึ้น ต่อมาคือการพัฒนาจะเร็วขึ้น บางคนอาจจะบอกว่า เราต้องทำงานเพิ่มขึ้นมันน่าจะช้าลงสิ แต่ถ้าลงในรายละเอียดแล้วจะพบว่า เวลาในการเตรียมข้อมูลสำหรับทดสอบนั้น จะน้อยกว่าเวลาที่ต้องรอให้ฝั่ง Server-side API พัฒนาเสร็จ จะน้อยกว่าเวลาที่ต้องรอให้ฝั่ง Server-side API แก้ไขข้อผิดพลาดเสร็จ นักพัฒนา Mobile app จะได้มีสมาธิสำหรับการพัฒนา app นั่นคือ ทำเพียงเรื่องเดียวในช่วงเวลาหนึ่ง ๆ แน่นอนว่า มันย่อมส่งผลให้ผลงานออกมาดี ทำให้คุณรู้ว่าสิ่งที่คุณกำลังทำอยู่นั้นมันใช่หรือไม่ !! เนื่องจากเมื่อเราจำลองส่วนการทำงานอื่น ๆแล้ว เราสามารถทดสอบและใช้งาน Mobile app ได้เร็วขึ้น ดังนั้นทำให้ได้รับ feedback ที่รวดเร็วขึ้น ทำให้เราพร้อมรับต่อการแก้ไขและเปลี่ยนแปลง ทำให้โครงสร้างของ code เปลี่ยนไป เนื่องจากถ้าต้องการเปลี่ยนไปมาระหว่างของจริงกับของปลอม คุณจะทำอย่างไรเพื่อลดการแก้ไข code ถ้ายังมาทำการ comment code หรือ มาเปลี่ยน code ไปมาตลอด แสดงว่ามาผิดทางอย่างแน่นอน ทำให้นักพัฒนา Mobile app และ Server-side API สามารถทำงานไปพร้อม ๆ กันได้ดี ไม่ต้องรอกันอีกต่อไป แต่จำเป็นต้อง integrate กันบ่อย ๆ สุดท้ายสามารถทำให้เราทดสอบ Mobile app ได้ง่ายขึ้น เช่นการทำ User Interface Testing (UI Testing) เนื่องจากเราสามารถกำหนดข้อมูลในการทดสอบได้ ทำให้สามารถทดสอบซ้ำ ๆ ได้เสมอ ทำให้มั่นใจได้ว่าระบบทำงานได้อย่างถูกต้องตามที่คาดหวัง

แต่สุดท้ายคุณต้องทำการ integrate กันจริง ๆ อยู่อย่างบ่อย ๆ

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

ว่าด้วยเรื่องของ Delegator และ Callback ใน Swift

$
0
0

lego-00

lego-00 วันนี้นั่งดูและเขียน code ด้วยภาษา Swift สำหรับพัฒนา iOS app พบว่าในหลาย ๆ ส่วนการทำงานใช้ Delegate pattern เพื่อเชื่อมต่อการทำงานในแต่ละส่วน เช่น
  • User Interface
  • Data model
  • Networking layer
  • Service layer
  • Helper class
มีเป้าหมายเพื่อไม่ให้ code ผูกติดกันมากจนเกินไป หรือ เรียกว่า Loose coupling แต่ละส่วนแยกกันทำงานชัดเจน แต่ทำให้ code ที่พัฒนาด้วยภาษา Swift เต็มไปด้วย protocol !!
คำถามที่น่าสนใจคือ มันมีวิธีการอื่นที่ดีกว่านี้ไหม ?

ก่อนอื่นมาทำความรู้จักกับ Delegator หรือ Listener

ว่า code ที่พัฒนาด้วยภาษา Swift มันมีรูปแบบอย่างไรบ้าง ? ตัวอย่าง code การทำงานระหว่าง ViewController กับ Network layer โดยในส่วนของ ViewController จะทำการแสดงข้อมูล ก็ต่อเมื่อในส่วนของ Network layer ทำการดึงข้อมูลเสร็จสิ้น ไม่ว่าจะสำเร็จ หรือ เกิดข้อผิดพลาดก็ตาม โดยในส่วนของ ViewController ไม่มีความจำเป็นต้องหยุดรอข้อมูลจาก Network layer เลย ดังนั้นเราจำเป็นต้องมีคนกลางหรือตัวแทน ของ Network layer เพื่อมาเชื่อมการทำงานกับ ViewController หรือเรียกส่วนนี้ว่า Delegator นั่นเอง เพื่อความไม่งง มาดู code ตัวอย่างกันดีกว่า ซึ่งมักจะสร้าง Delegator ด้วย protocol ดังนี้ [gist id="c4801f76d04041bfeb645392645431ac" file="NetworkDelegator.swift"] จากนั้นในส่วนของ Network ที่ทำหน้าที่ดึงข้อมูลจาก API ก็ทำการสร้างตัวแปรสำหรับ delegator มาซะ ดังนี้ [gist id="c4801f76d04041bfeb645392645431ac" file="MyNetwork.swift"] สุดท้ายทาง View Controller ก็ทำการ implement protocol NetworkDelegator ซะ จากนั้นจึงเริ่มใช้งาน [gist id="c4801f76d04041bfeb645392645431ac" file="MainViewController.swift"] ทำให้เราสามารถแยกส่วนการทำงานต่าง ๆ ออกจากกันอย่างชัดเจน คือ
  • ViewController ทำหน้าที่แสดงผล และ ดักจับการใช้งานจากผู้ใช้งาน
  • Network ทำหน้าที่ดึงข้อมูลจาก API ผ่านระบบ Network
  • Delegator คือตัวกลางที่ช่วยทำให้ทั้ง ViewController และ Network ทำงานร่วมกับแบบหลวม ๆ และทำงานแบบ Asynchronuous

ทุกอย่างทำงานได้ดี ปกติ ไม่มีปัญหาอะไรเลย

แต่เมื่อมานั่งคิดดู ถ้าไม่อยากส่งค่าของ delegator จาก ViewController ไปยัง Network ได้หรือไม่ ? ถ้าใน ViewController มี delegator จำนวนมาก ก็ไม่น่าจะสนุก หรือ ดีนะ ? เพราะว่า ต้องส่ง object reference ของ delegator ไป ดังนั้นมีวิธีอะไรที่ดีกว่านี้หรือไม่ ?

หนึ่งในแนวคิดที่น่าสนใจคือ Callback

ซึ่งมีแนวคิดคล้าย ๆ กับ Delegate เลย ต่างกันเพียงแทนที่จะส่ง object reference ไป ก็ให้ส่ง function กันไปเลย โดยในภาษา Swift นั้น function คือ first class อยู่แล้ว จะรอช้าไปทำไมเขียน code กันดีกว่า เริ่มจากการแก้ไขไฟล์ MyNetwork.swift ด้วยการสร้าง callback function ชื่อว่า onSuccess ขึ้นมา เพื่อให้ทาง ViewController เรียกใช้งาน [gist id="c4801f76d04041bfeb645392645431ac" file="MyNetwork2.swift"] จากนั้นทางฝั่ง ViewController ก็เรียกใช้ง่าย ๆ โดยเรียกตรงมายัง MyNetwork เลย ไม่จำเป็นต้องมี Delegator อีกต่อไป ดังนี้ [gist id="c4801f76d04041bfeb645392645431ac" file="MainViewController2.swift"] จะเห็นได้ว่าเราสามารถนำ callback มาใช้แทน delegator ได้เลย แถมมันเป็นสิ่งที่มีมาใน swift อยู่แล้ว แถมลดจำนวน code ลงไปอีกนะ แถมนำไปใช้กับ property observer ของตัวแปรต่าง ๆ ได้อีกด้วย รวมทั้งช่วยทำให้สามารถทดสอบระบบงานได้ง่ายกว่าเดิมอีก ลองใช้แล้วจะติดใจ !! ปล. ทั้งสองเรื่องนี้คือพื้นฐานที่นักพัฒนาไม่ควรพลาด แถมมันยังเป็นพื้นฐานของ Reactive Programming อีกด้วย
วันนี้ Swift developer ใช้แบบไหนกันอยู่บ้าง ?
Source code ตัวอย่างอยู่ที่ Github :: Up1

สรุปข้อแตกต่างระหว่าง SOA และ Microservice ไว้นิดหน่อย

$
0
0

Microservices-vs-SOA

Microservices-vs-SOA ในปัจจุบันไปงานไหน ๆ ก็มีแต่คนพูดถึง Microservice ว่ามันดีอย่างนั้นอย่างนี้ แต่สำหรับใครก็ตามที่มีประสบการณ์กับ SOA (Service Oriented Architecture) หรือบางคนอาจจะเรียกว่า Service Oriented Ambiguity ก็ตาม
อาจจะเกิดคำถามขึ้นมาว่า ทั้ง SOA และ Microservice มันเหมือนหรือแตกต่างกันอย่างไรบ้าง ?

SOA ย่อมาจาก Service Oriented Architecture

เป็นรูปแบบหนึ่งของการออกแบบสถาปัตยกรรม Software โดยทำการแยกส่วนการทำงานออกเป็น component ในแต่ละ component ประกอบไปด้วย service ต่าง ๆ ซึ่งทำงานอย่างใดอย่างหนึ่งไปเลย เช่น
  • Shopping cart service
  • Account activation service
  • Order validation service
  • Order status service
รวมทั้งยังได้กำหนด protocol ในการสื่อสารอย่างง่ายระหว่าง component ไว้อีกด้วย โดยใน SOA ประกอบไปด้วย 2 ส่วนหลักคือ
  1. Consumer คือ ผู้ใช้งานทั้งจากผู้ใช้งาน จาก service อื่น และ ระบบอื่น
  2. Provider คือ ผู้ใช้บริการ service ต่าง ๆ
แสดงดังรูป soa-01 จากรูปจะเห็นว่ามีส่วนที่เรียกว่า Enterprise Service Bus (ESB) เป็นสถาปัตยกรรมหนึ่งที่รวมเอาส่วนการทำงานต่าง ๆ มาทำงานร่วมกัน ทั้ง Consumer และ Provider นั่นคือช่องทางนการติดต่อสื่อสารนั่นเอง ทำให้ส่วนการทำงานต่าง ๆ สามารถแบ่งปันและแลกเปลี่ยนข้อมูลกันได้ง่าย แต่บ่อยครั้งที่พบว่า ESB กลับกลายเป็นปัญหา !!

มาดู Microservice Architecture กันบ้าง

เป็นรูปแบบหนึ่งของการออกแบบสถาปัตยกรรมของ Software ซึ่งแยกส่วนการทำงานใหญ่ ๆ ออกเป็นส่วนเล็ก ๆ โดยแต่ละส่วนเรียกว่า service แต่ละ service มีขนาดเล็ก แต่ไม่ใช่เล็กแบบ function หรือ method นะ แต่ละ service แยกกันทำงานอย่างชัดเจน แต่ละ service แยกส่วนจัดเก็บข้อมูลออกจากกัน แต่อาจจะ share กันได้บางกรณี แต่ละ service สามารถพัฒนาด้วยภาษาโปรแกรมที่ต่างกัน แต่ละ service ติดต่อสื่อสารกันผ่าน protocol ที่กำหนดร่วมกัน แต่ละ service เป็นอิสระต่อกัน ทำให้สามารถ deploy โดยไม่กระทบ (แต่ต้องทดสอบดี ๆ นะ) แต่ละ service สามารถปิด หรือ ล่มได้ โดยไม่ส่งผลกระทบต่อ service อื่น !! (Design for failure) แต่การออกแบบและพัฒนาไม่ง่ายเลย !! แสดงดังรูป soa-02

แล้ว SOA กับ Microservice มันแตกต่างกันอย่างไร ?

ในมุมมองนักพัฒนาของผมชอบภาพนี้ มันอธิบายได้ชัดเจนมาก ๆ soa-04 โดยแต่ละ service ของ SOA และ Microservice สามารถแบ่งไปให้แต่ละทีม หรือ หลาย ๆ ทีมพัฒนาได้ สามารถใช้เทคโนโลยีในการพัฒนาที่แตกต่างกันได้
แต่สิ่งที่แต่ละทีมต้องตกลงร่วมกันก่อนคือ รูปแบบของการติดต่อสื่อสารระหว่าง service ว่าเป็นอย่างไร
แต่ว่า service ใน SOA มักจะไม่เป็นอิสระต่อกัน  !! ซึ่งต่างจาก Microservice ส่งผลให้ Microservice นั้น deploy ได้ง่ายกว่า scale ระบบได้ง่ายกว่า
ส่วนใน SOA นั้น ESB กลับกลายเป็นปัญหาใหญ่ของทั้งระบบ หรือเป็น Single Point of Failure (SPoF) เนื่องจากแต่ละ service ต้องทำการติดต่อสื่อสารผ่าน ESB
ส่วนเรื่องของการ share ข้อมูลระหว่าง service นั้น มีทั้งข้อดีและข้อเสีย ซึ่งต้องพิจารณาให้ดี ๆ ข้อดีคือแต่ละ service สามารถใช้ข้อมูลร่วมกันได้ง่าย ข้อเสียคือแต่ละ service จะผูกมัดกันอย่างมาก (Tight coupling)

โดยสรุปแล้ว SOA และ Microservice นั้นต่างกันที่

ขนาดและขอบเขตการทำงาน โดยที่ Microservice จะมีขนาดเล็กกว่า SOA และแต่ละ service เป็นอิสระต่อกันมากกว่า SOA ส่วน SOA นั้นสามารถประกอบมีระบบแบบ Monolith และ Microservice อยู่รวมกันได้ เนื่องจาก SOA นั้นถูกออกแบบและสร้างขึ้นมา เพื่อทำให้ระบบที่แตกต่างกันสามารถทำงานร่วมกันได้ผ่านระบบ ESB จึงไม่แปลกใจเลยว่า เมื่อพูดถึง SOA เมื่อใด จะมี ESB ตามมาติด ๆ เสมอ แสดงดังรูป soa-03 Reference Websites http://martinfowler.com/articles/microservices.html http://microservices.io/patterns/microservices.html http://stackoverflow.com/questions/25501098/difference-between-microservices-architecture-and-soa https://dzone.com/articles/microservices-vs-soa-2

เมื่อนักพัฒนาไม่สามารถควบคุมความซับซ้อนของ code ได้ !!

$
0
0

mess-00

mess-00 จากบทความเรื่อง Why it happens to your code again and again? อธิบายการพัฒนาระบบ web application ด้วย RoR (Ruby on Rails) ซึ่งเป็น framework หลักของการพัฒนาระบบด้วยภาษา Ruby โดยในช่วงแรกของการพัฒนาระบบนั้นจะราบรื่นและรวดเร็ว ไม่ว่าจะเป็นการเพิ่ม gem หรือ library ต่าง ๆ เข้าไป ทุกอย่างมันแจ่มมาก ๆ

แต่เมื่อเวลาผ่านไปเรากลับพบว่า

ยิ่งทำการเพิ่ม feature ใหม่ ๆ เข้ามา ยิ่งทำการเพิ่ม gem หรือ libray ต่าง ๆ เข้ามา การพัฒนากลับยิ่งช้าลง การพัฒนาเป็นแบบปะผุไปวัน ๆ หรือ ทำให้มันเสร็จ ๆ ไป code ของแต่ละส่วนผูกมัดกันเหลือเกิน แก้ไขจุดหนึ่งกระทบไปอีกหลายจุด ยิ่งทำการ update version ของ gem หรือ library ด้วยแล้ว ยิ่งไปกันใหญ่ แสดงดังรูป cycle

มีหลาย ๆ คนคิดจะแก้ไขและปรับปรุงให้ดีขึ้น

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

ดังนั้นนักพัฒนาที่ดีต้องมีความสามารถดังนี้

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

คำถามคือ แล้วต้องทำอย่างไรบ้าง ?

สิ่งที่นักพัฒนาที่ดีควรต้องทำก่อนคือ การจัดการความซับซ้อนให้ลดน้อยลงไปให้ได้ นั่นคือ ต้องทำการปรับปรุงความสามารถต่าง ๆ ขึ้นมา ลองถามตัวเราเองสิว่า รู้แล้วเข้าใจสิ่งต่าง ๆ เหล่านี้หรือไม่ ? ถ้ายังศึกษาซะ
  • SOLID principles
  • Design patterns
  • Refactoring
  • Code smell
  • Testing
  • รูปแบบต่าง ๆ ของ Architecture

จากนั้นทำการศึกษาและเรียนรู้เครื่องมือต่าง ๆ

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

นักพัฒนาที่ดีควรหลีกเลี่ยงการตั้งชื่อที่แย่ ๆ

$
0
0

hard-dev-02

อ้างอิงข้อความจากคุณ Phil Karlton
There are only two hard things in Computer Science: cache invalidation and naming things.
รวมทั้งข้อมูลจากผลสำรวจเรื่อง The hardest problem in programming is what to name your variables and functions พบว่าเรื่องที่ยากที่สุดสำหรับนักพัฒนา software คือ การตั้งชื่อของตัวแปร function/method, class และอื่น ๆ อีกมากมาย โดยรวมคือการตั้งชื่อให้สื่อความหมายนั่นเอง (Meaningful Name) เรื่องรองลงมาเช่น
  • ไม่สามารถอธิบายได้ว่าตัวเองกำลังทำอะไร
  • ไม่สามารถประเมินเวลาในการทำงานได้
  • มีปัญหาในการทำงานร่วมกับผู้อื่น
สรุปแล้วนักพัฒนา software ทำอะไรกันอยู่ล่ะ ? และ code ที่เขียนออกมามันเป็นอย่างไรกันบ้าง ? หรือเราสนใจเพียงผลการทำงานที่เห็นเท่านั้น !!
แสดงดังรูป hard-dev-02 สำหรับนักพัฒนา software ที่ดีนั้นต้อง สามารถปรับปรุงการตั้งชื่อให้ดีขึ้น สามารถปรับปรุงชื่อให้สื่อความหมายและเข้าใจได้มากขึ้น สามารถลด code ที่ซ้ำซ้อนลงไปได้

แต่เรากลับพบ code จำนวนมากที่ตั้งชื่อแย่ ๆ และ ไม่สื่อความหมายอะไรเลย !!

ลองค้นหาคำว่า foo ใน github.com ได้ข้อมูลดังนี้ เยอะดีนะ !! คำว่า foo มันไม่ได้มีความหมายอะไรเลย hard-dev-03

ตัวอย่างของชื่อตัวแปรที่แย่สุด ๆ คือ data

รองลงมาคือ data2 ถัดลงมาคือ data_2 ลด ล่ะ เลิกการใช้ตัวย่อสักทีเถอะนะ (ยกเว้น id ไว้ก็ได้) เช่น
  • acc
  • inq
  • pos
  • auth
  • mod
ส่วนพวก local variable ก็เลิกการตั้งชื่อสั้น ๆ เพียง 1 ตัวอักษรนะ เช่น i, j, k, x, y ,z
บางคนบอกว่างั้นใช้ 2 ตัวอักษรก็ได้ เช่น xx, yy, zz ขอบอกเลยว่า มันไม่ได้ช่วยปรับปรุงห่าเหวอะไรเลยนะ !!
อีกเรื่องที่พบมาก ๆ คือการสะกดชื่อคำศัพท์ต่าง ๆ ผิด เขียนผิด ความหมายเปลี่ยนทันที !! ดู Antipattern แบบขำ ๆ ของการตั้งชื่อเพิ่มเติมได้จาก Programming Puns

ยังไม่พอนะ จาก Paper เรื่อง Linguistic antipatterns: what they are and how developers perceive them

อธิบายถึงแนวปฏิบัติแย่ ๆ ที่เกิดขึ้นอย่างซ้ำซากในการพัฒนา software คือ การตั้งชื่อ, เอกสาร และ การอธิบายพฤติกรรมการทำงานของระบบ ซึ่งทำการสรุปไว้ 17 กลุ่มดังนี้
  1. Getter method ทำมากกว่าการ return ค่ากลับมา โดยไร้ซึ่งเอกสารมาอธิบาย
  2. isXXX method ทำการ return ค่าอื่น ๆ ที่ไม่ใช่ boolean
  3. Setter method ทำการ return ค่ากลับออกมาได้
  4. ชื่อของ method บอกว่า return ค่าเพียงค่าเดียว แต่ว่าในความจริงกลับส่ง List/Array หรือ Null กลับมา เช่น List getUser()
  5. Comment ของ method บอกว่ามีเงื่อนไขต่าง ๆ แต่ใน code กลับไม่มี
  6. ใน method มักจะมีการ validate ข้อมูล แต่ไม่แจ้งความผิดพลาดใด ๆ ออกมาเลย ทำงานได้ในกรณีที่สำเร็จเท่านั้น โดยไม่มีเอกสารอะไรมาอธิบาย
  7. Getter method ไม่ทำการ return ค่าอะไรเลย
  8. ชื่อของ method ไม่สื่อถึงการทำงานจริง เช่น void isValid()
  9. method ที่ทำการแปลงค่าจากค่าหนึ่งไปยังอีกค่าหนึ่ง ไม่ทำการ return ค่าออกมา
  10. ชื่อของ method บอกว่า return ค่ามากกว่าหนึ่งตัวเช่น List/Array แต่ว่าในความจริงกับส่งเพียงตัวเดียวกับมาเช่น int getUsers()
  11. ชื่อ method กับชนิดของการ return ขัดแย้งกัน
  12. ชื่อ method และ comment ของ method ขัดแย้งกัน
  13. ชื่อตัวแปรเป็นเอกพจน์ แต่กลับมีค่าเป็นพหูพจน์ เช่น List user
  14. ชื่อตัวแปรเป็นพหูพจน์ แต่กลับมีค่าเป็นเอกพจน์ เช่น User users
  15. ชื่อบอกว่าเป็นชนิด boolean แต่ความจริงกลับไม่ใช่
  16. ชื่อและชนิดของตัวแปรขัดแย้งกัน
  17. ชื่อและ comment ของตัวแปรขัดแย้งกัน
ลองกลับมาถามตัวเราเองสิว่า ทำข้อไหนกันอยู่บ้าง ?

คำถามที่น่าสนใจคือ แล้วจะปรับปรุงการตั้งชื่ออย่างไรดีล่ะ ?

ผมมีคำแนะนำดังนี้ เริ่มจากการเป็นผู้เขียนที่ดี จะเป็นผู้เขียนที่ดีได้ ต้องรู้จักคำศัพท์เยอะ ๆ (ภาษาอังกฤษ) ดังนั้นจำเป็นต้องอ่านเยอะ ๆ อ่านในสิ่งที่เราสนใจก่อนน่าจะง่ายที่สุด หรือเล่นเกมส์เพื่อฝึกคำศัพท์เช่น Crossword เป็นต้น หรือไม่เช่นนั้นก็เริ่มใช้งาน dictionary บ้างนะ ต่อมาให้เริ่มฝึกตั้งชื่อต่าง ๆ ใน code ให้เริ่มต้นจากการเข้าใจก่อนว่า เรากำลังจะทำอะไร (ยากมาก  ๆ) ใช้คำที่มันสามารถสื่อสารความต้องการของเราได้ โดยไม่จำเป็นต้องใช้คำเยอะ ลด ละ เลิกการใช้ตัวย่อ ทำการ pair programming และ code review เพื่อปรับปรุงการตั้งชื่อ ถ้าต้องการแก้ไขชื่อ แนะนำให้ทำผ่าน refactoring tool ของ IDE ที่ใช้นะครับ จะปลอดภัยและสะดวกที่สุด ไม่ใช่ทำการค้นหาและ replace ทั้งหมดนะ !! ทำแบบนี้ไปเรื่อย ๆ ปรับปรุงอย่างต่อเนื่อง แล้วการตั้งชื่อของเราจะดีขึ้นเอง
ปล. การตั้งชื่อที่ว่ายากแล้ว การเปลี่ยนชื่อสิยากยิ่งกว่า
สรุปง่าย ๆ คือ ให้เวลากับการตั้งชื่อ ทำ code review บ่อย ๆ อย่ากลัวการเปลี่ยนชื่อ และทำบ่อย ๆ จนกลายเป็นเรื่องธรรมชาติ

หนังสือที่แนะนำให้อ่านและศึกษาเพิ่มเติมสำหรับการตั้งชื่อมีดังนี้

  • Code complete บทที่ 10 เรื่อง The power of variable names
  • Clean code บทที่ 2 เรื่อง Meaningful names
  • Becoming a better programmer บทที่ 2 เรื่อง Names

สุดท้ายแล้ว

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

Regression Testing คืออะไร ?

$
0
0

regression

regression เช้านี้อ่านเจอบทความเรื่อง What is Regression Testing ? ทำการอธิบายเกี่ยวกับ Regression testing ว่าคืออะไร ? มีเป้าหมายเพื่ออะไร ? และจะลงมือทำการทดสอบเมื่อใด ? จึงทำการสรุปการอ่านไว้นิดหน่อย

Regression Testing คืออะไร ?

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

คำถามต่อมาคือ Functional testing มันคืออะไรล่ะ ?

เป็นการทดสอบ และ เป็นขั้นตอนที่ถูกสร้างขึ้นมาเพื่อ ใช้ยืนยันว่าแต่ component ของระบบ ทำงานร่วมกันได้อย่างถูกต้องตามความต้องการที่ตกลงไว้ร่วมกัน โดยเน้นที่การทดสอบจาก interface ของระบบงาน เพื่อทำให้มั่นใจว่าระบบงานนั้นสามารถทำงานได้อย่างเหมาะสมกับผู้ใช้งาน เช่น ถ้าเป็นระบบ Web application ก็เน้นไปที่ User Interface บน browser ถ้าเป็นระบบ API ก็เน้นไปที่การใช้งานผ่าน API Functional testing ประกอบไปด้วยการทดสอบชนิดต่าง ๆ ดังนี้
  • Smoke testing
  • Sanity testing
  • Integration testing
  • Acceptance testing
  • Regression testing

คำถามต่อมาคือ ทำ Regression testing ตอนไหน ?

Regression testing เป็นการทดสอบที่สำคัญมาก ๆ ของการพัฒนา software จะลงมือทำเมื่อ
  • ทำการ release ระบบ หรือ feature ใหม่ ๆ
  • เมื่อทำการแก้ไขข้อผิดพลาดต่าง ๆ ที่สำคัญ
ถ้าจะให้ดีมาก ๆ ชุดการทดสอบของ Regression testing นั้น ควรทำการทดสอบอยู่อย่างบ่อย ๆ ควรทำการทดสอบอย่างรวดเร็ว เพื่อทำให้เรารู้ปัญหาได้อย่างรวดเร็ว เพื่อทำให้เราแก้ไขปัญหาได้อย่างรวดเร็ว ถ้าจะให้ดีมากขึ้นไปอีก ให้เริ่มต้นทำตั้งแต่วันแรกของการพัฒนาเลย เริ่มจากง่าย ๆ ก่อนเป็นดีที่สุด บางคนอาจจะบอกว่า เป็นไปไม่ได้หรอก แต่ผมขอแนะนำว่า ให้ลองทำเถอะนะ
คำว่าเป็นไปไม่ได้ มันคืออะไร ? ไม่เคยทำ หรือ ทำไม่เป็น หรือ ... ดังนั้นลงมือทำเถอะครับ ถ้าไม่ลงมือทำสักทีจะทำเป็นหรือไง ?

เนื่องจากทุกการเปลี่ยนแปลงของระบบล้วนมีความเสี่ยง !!

ดังนั้นสิ่งที่นักพัฒนาต้องตอบให้ได้คือ
  1. สิ่งที่สร้างและแก้ไขไปนั้น มันทำงานได้อย่างถูกต้องหรือไม่ ?
  2. สิ่งที่สร้างและแก้ไขไปนั้น มันไม่ส่งผลกระทบต่อการทำงานในส่วนอื่น ๆ หรือไม่ ?
ยิ่งถ้าทีมพัฒนามีระบบพวก Continuous Integration และ Continuous Delivery ด้วยแล้ว แนะนำให้นำเอา Regression testing เข้ามาอยู่ในระบบนี้เสมอ เพราะว่าจะทำการทดสอบทุกครั้ง เมื่อ code มีการเปลี่ยนแปลง ซึ่งมันแจ่มมาก ๆ และควรทำอย่างแรงนะครับ แสดงการทำงานดังรูป what-is-regression-testing

สุดท้ายแล้ว ถ้าเราต้องการป้องกันความผิดพลาด

ก็ต้องทำการค้นหาความผิดพลาดให้รวดเร็วที่สุดนั่นเอง เนื่องจากยิ่งค้นหาได้ช้า ค่าใช้จ่ายสำหรับการแก้ไขก็ยิ่งแพงนะครับ และลด ละ เลิกการ debug เถอะนะ หรือว่าคนจริงต้องแก้ไขข้อผิดพลาดบน Production กันนะ !! https://www.youtube.com/watch?v=75wa8Lx4yc4

[Update] การติดตั้ง Robot Framework บนระบบปฏิบัติการ Windows 

$
0
0

robot-00

robot-00 แก้ไขสำหรับการติดตั้ง Robot Framework บนระบบปฏิบัติการ Windows Software ที่ใช้ในการติดตั้งประกอบไปด้วย
  • Python 2.7.12
  • เพิ่มเติมสำหรับ Text editor ที่ใช้เขียน script ของ Robot framework คือ Sublime และ Atom
  • Default browser คือ Firefox
มีขั้นตอนการติดตั้งดังต่อไปนี้

1. ทำการ Download Python 2.7.12

เนื่องจาก Robot framework นั้นพัฒนาด้วยภาษา Python นะครับ

2. เมื่อ Download เสร็จแล้ว ให้ทำการติดตั้ง Python

โดยทำการกด next, next และ next อย่างเดียว จะติดตั้ง Python ไว้ที่ c:\Python27 ซึ่งขอเรียกว่า PYTHON_HOME

3. ทำการตรวจสอบว่า สามารถใช้งาน Python ผ่าน command line

ทำการเปิด command line แล้วพิมพ์คำสั่งดังนี้ [code] python [/code] ถ้าผลการทำงานเกิด Error ดังนี้ [code] python is not recognised as an internal or external command [/code] ให้ทำการแก้ไขดังนี้ 3.1 ทำการกำหนด Environment variable แบบชั่วคราว ใน command line ให้พิมพ์คำสั่งดังนี้ [code] set PYTHON_HOME=c:\Python27 set PATH=.;%PYTHON_HOME%;%PYTHON_HOME%\scripts;%PATH% [/code] จากนั้นให้พิมพ์คำสั่ง python อีกครั้ง จะไม่เขียน error อีกแล้ว แต่เมื่อทำการปิด command line ไป แล้วเปิดขึ้นมาใหม่ จะเกิด error เช่นเดิม เนื่องจากเป็นการกำหนด Enronment variable แบบชั่วคราวเท่านั้น 3.2 ทำการกำหนด Environment variable แบบถาวร ทำการแก้ไขโดยไปที่ System Properties เข้าไปด้วย Click ขวาที่ My Computer -> เลือก Properties -> เลือก tab Advance และเลือก Environment variables ดังรูป robot-01 ให้ทำการสร้าง แก้ Environment Variables ในส่วนของ System Variable หรือ User Variable ก็ได้ โดยใส่ค่าดังนี้ 1. ทำการกำหนด PYTHON_HOME สำหรับกำหนด path ที่ติดตั้ง Python Variable=PYTHON_HOME Value=c:\Python27 2. ทำการกำหนด PATH Variable=PATH Value=.;%PYTHON_HOME%;%PYTHON_HOME%\scripts;%PATH% แสดงดังรูป robot-02 จากนั้นทำการกด ok ok ok และปิด command line แล้วทำการเปิด command line ขึ้นมาใหม่ พิมพ์คำสั่ง python จะไม่เกิด error อีกแล้ว

4. ทำการทดสอบใช้งาน pip ใน command line

คือตัวจัดการ package/library ต่าง ๆ สำหรับภาษา Python โดยจะมีมากับ Python 2.7.9 เป็นต้นมา ดังนั้นไม่ต้องทำการติดตั้งแต่อย่างใด ซึ่งจะอยู่ใน folder %PYTHON_HOME%\Scripts ทำการเปิด command line แล้วพิมพ์คำสั่ง [code] pip [/code] จะต้องไม่เกิด error ใด ๆ ขึ้นมา แสดงผลการทำงานดังนี้ robot-05

5. ทำการติดตั้ง Robot Framework ผ่าน pip

ทำการติดตั้ง robotframework ซึ่งเป็น library หนึ่งที่พัฒนาด้วยภาษา Python โดยจะติดตั้งผ่าน pip ด้วยคำสั่ง [code] pip install robotframework [/code] ต่อมาทำการติดตั้ง library สำหรับการทดสอบระบบ web application ชื่อว่า robotframework-selenium2library ด้วยคำสั่ง [code] pip install robotframework-selenium2library [/code] ทำการตรวจสอบผลการติดตั้ง robotframework ด้วยคำสั่ง [code] pybot [/code] จะต้องแสดงผลการทำงานดังนี้ เป็นอันเรียบร้อย พร้อมสำหรับการเขียนชุดการทดสอบด้วย Robot Framework แล้ว robot-04

6. ทำการติดตั้ง Text Editor สำหรับเขียน script ด้วย Robot Framework

แนะนำให้ทำการติดตั้ง Sublime หรือ Atom ก็ได้ เพื่อความสะดวกสบายในการเขียน script ต่อไป เพียงเท่านี้เราก็พร้อมเริ่มต้นไปกับ Robot Framework แล้วนะครับ สำหรับการติดตั้งแบบเก่าอ่านได้จาก การติดตั้ง Robot Framework บนระบบปฏิบัติการ Windows

เมื่อ MVC ย่อมาจาก Massive ViewController

$
0
0

mvc

mvc เมื่อวานนั่งดู Code การพัฒนา iOS ด้วยภาษา Swift โจทย์เดียวกันจาก developer 4 คน แต่โครงสร้างของ code ที่ออกมานั้นเหมือนกัน นั่นคือเป็น MVC(Model View Controller) ในรูปแบบของ Apple ซึ่งส่วนใหญ่จะนำไปสู่ MVC ที่ย่อมาจาก Massive ViewController มากกว่านะ !! และนั่นคือความหายนะที่กำลังมาเยือนนักพัฒนาโดยทั้งรู้และไม่รู้ตัว

คำถามที่น่าสนใจคือ แล้ว MVC มันไม่ดีหรือไง ?

ตอบได้เลยว่าดีนะ ถ้าเข้าใจ และ ใช้งานได้อย่างถูกต้อง

คำถามต่อมา แล้วโครงสร้างแบบอื่นที่ดี ๆ ทำไมไม่ใช้กัน ?

ทั้ง MVP, MVVM และ VIPER เป็นต้น แต่ก่อนจะเลือกอะไรนั้น นักพัฒนาลองตอบคำถามเหล่านี้ก่อนสิ
  • เรื่องการการเรียกใช้งาน API ผ่านระบบ network ควรอยู่ตรงไหนดี Model หรือ Controller ?
  • จะทำการส่ง Model ไปยัง View เพื่อแสดงผลอย่างไร ?
  • ปัจจุบันเขียน code อย่างไร ?
  • ทดสอบกันแบบไหน ?
ถ้ายังงง ๆ ตอบไม่ถูก แสดงว่าอย่าเพิ่งทำอะไรเลยนะ มาทำความเข้าใจและเรียนรู้ จากนั้นมาฝึกฝนกันก่อน

คำถามต่อมา เราจะสนใจเรื่องโครงสร้างของระบบไปทำไม ?

ถ้านักพัฒนาไม่เลือกหรือกำหนดตั้งแต่แรก มันมักจะก่อให้เกิด class ขนาดใหญ่หรือ God class จำนวนมากมาย ยากต่อการค้นหาและแก้ไขอย่างมาก หรือแค่มานั่งไล่ code เพื่อทำความเข้าใจก็ยังยากเลย !! เรื่องของโครงสร้างมันก็สัมพันธ์กับความสามารถของทีมเช่นกัน

มาดูตัวอย่างจาก code ของ iOS app ที่พัฒนาด้วยภาษา Swift

จะมีลักษณะดังนี้
  • ทำการ extends มาจาก UIViewController
  • ข้อมูลต่าง ๆ ที่จะทำการแสดงผลหรือดึงข้อมูลจากภายนอกก็อยู่ใน UIViewController นี่แหละ
  • ส่วนของ UIViews ไม่ได้ทำอะไรเลย
  • Model ก็เป็นเพียง class และ struct สำหรับกำหนดโครงสร้างของข้อมูลเท่านั้น
  • UI testing อย่าคิด ส่วน Unit testing อย่าฝันว่าจะมี
ซึ่งเป็นผลมาจาก MVC ของ Apple นั่นเอง เมื่อเข้าไปดูเอกสารเรื่อง MVC จากทาง Apple แล้วพบรูปนี้ ซึ่งมันแจ่มมาก ๆ model_view_controller_2x

แต่เมื่อนำมา implement จริง ๆ กลับได้แบบนี้ !!

นั่นคือ ViewController ผูกติดกลายเป็นตัวเดียวกันไปเลย mvc-apple ซึ่งเป็นโครงสร้างที่เอื้อต่อการสร้าง Massive ViewController อย่างมาก เนื่องจากทำการรวม View Life Cycle เข้ากับ Controller ทำให้พวก business logic ต่าง ๆ รวมอยู่ในนั้นด้วย ทำได้เพียงแยกส่วนของ data หรือ Model ออกมาเท่านั้น ทำให้ใน ViewController นั้นจะใช้งานพวก Delegate และ Datasource ของทุก ๆ อย่างเสมอ เช่น TableView และ SwipeView เป็นต้น ผลที่ตามมาคือ View คุยกับ Model โดยตรง หรือ ทำการส่ง Model ไปให้ View ซะงั้น !! นั่นคือ ข้อขัดแย้งอย่างรุนแรงต่อ MVC และเราพบเห็นได้บ่อยมาก ๆ ใน ViewController ของ iOS app และนักพัฒนาทุกคนก็มองว่า มันเป็นเรื่องปกติ ไม่ได้ผิดอะไร !! เมื่อเวลาผ่านไปนานขึ้น ขนาดของ ViewController ต่าง ๆ ก็ใหญ่โตขึ้นเรื่อย ๆ นี่แหละคือที่ไปที่มาของ Massive ViewController ยังไม่พอนะ เมื่อต้องเขียน Unit testing ด้วยแล้ว !! ปัญหามันหนักมาก ๆ เนื่องจาก ViewController มันเยอะไปหมด code ผูกติดกันอย่างแน่นหนา ทั้ง View ทั้ง Controller ทั้ง Business logic หวังว่าระบบที่พัฒนาหรือดูแลกันอยู่ ไม่น่าจะเป็นเช่นนี้นะครับ

ดังนั้นสิ่งที่ควรทำก่อนเลยก็คือ

ทำความเข้าใจกับ code และลองเขียนออกมาหน่อยว่า ใน ViewController มีหน้าที่การทำงานอะไรบ้าง จากนั้นค่อย ๆ แยกส่วนการทำงานต่าง ๆ ออกมา โดยในแต่ละส่วนก็ช่วยเขียน Unit test ขึ้นมาคลุมหน่อยนะครับ ค่อย ๆ ถอด ค่อย ๆ แยก ค่อย ๆ ทดสอบ ค่อย ๆ integrate แล้ว code จะค่อย ๆ ดีขึ้นเอง

ส่วน code ใหม่ ๆ ลองคิด วิเคราะห์ แยกแยะก่อนว่า

ในแต่ละ feature ต้องทำอะไร ต้องการอะไรบ้าง โดยแนะนำให้ทำดังนี้
  • แยกส่วนการทำงานของ Model, View ออกจากกันก่อน
  • ส่วนของ Controller กับ View อาจจะยังติดกันนิดหน่อย
  • แต่ละส่วนการทำงานต้องสามารถทดสอบได้ แต่ถ้าคุณแยกส่วนการทำงานไม่ดีจะทดสอบได้ยาก หรือ ทำได้เพียง Model เท่านั้น ซึ่งต้องระวังให้มาก ๆ
  • Code แต่ละส่วนง่ายต่อการใช้งาน ง่ายต่อการดูแล แม้แต่นักพัฒนาที่มีประสบการณ์น้อยก็ตาม มิเช่นนั้นคุณจะเอาเทคนิคแปลก ๆ มาใช้จนคนในทีมงงไปเลย อย่าทำนะ !! มันจะเป็นการใช้งานที่มากเกินความจำเป็น
  • ของดีแต่อาจจะยังไม่เหมาะสมกับทีมในเวลานี้ก็เป็นได้
ดังนั้นการจะเลือกวางโครงสร้างของระบบอย่างไรนั้น มันมีปัจจัยหลาย ๆ อย่าง แต่เหนือสิ่งอื่นใด สิ่งที่คุณเลือกมันทำให้คุณและทีมช้าลงหรือเร็วขึ้น

ATDD, BDD, SbE มันต่างกันอย่างไร ?

$
0
0

atdd-00

atdd-00 มีคำถามที่น่าสนใจคือ ATDD, BDD และ SbE มันคืออะไร ? เหมือน หรือ แตกต่างกันอย่างไรบ้าง ? มีเป้าหมายเพื่ออะไรบ้าง ? จากนั้นจึงลองไปค้นหาคำตอบ ก็พบว่าเรื่องนี้เขาคุยกันมาตั้งแต่ปี 2010 แล้ว โดยทำการสรุปไว้ในบทความเรื่อง ATDD vs. BDD vs. Specification by Example vs …. จึงทำการแปลและสรุปไว้นิดหน่อย
ATDD ย่อมาจาก Acceptance Test Driven Development BDD ย่อมาจาก Behaviour Driven Development SbE ย่อมาจาก Specification by Examples

โดยเริ่มจากการพูดคุยว่าจริง ๆ แล้วนั้น ATDD มันคืออะไรกันแน่ ?

ทุกคนรู้ว่า Acceptance tests นั้นถูกกำหนดมาจาก ความต้องการของลูกค้า หรือ ทาง business ซึ่งจะเป็นตัวขับเคลื่อนกระบวนการ Test Driven Development (TDD) เพื่อสร้างระบบงานที่ตรงตามความต้องการนั่นเอง แต่คำที่แต่ละคนใช้เรียกต่างกันอย่างมาก เช่น
  • Examples
  • Scenarios
  • Acceptance tests
  • Customer tests
  • Behaviour
  • Business facing tests
  • Story tests
  • Functional tests
  • Acceptance criteria
  • Business rules
  • Executable specification
รวมทั้งมีคำอธิบายเกี่ยวกับ ATDD เยอะมาก ๆ ซึ่งหนึ่งในนั้นคือคำอธิบายจากคุณ Jennita Andrea ไว้ดังนี้ ATDD เป็นแนวปฏิบัติเพื่อทำให้เราได้ ตัวอย่างที่ชัดเจน ข้อตกลงต่าง ๆ ที่ชัดเจน ความคาดหวังต่าง ๆ ที่ชัดเจน ของแต่ละ function, story หรือ requirement ก่อนเริ่มพัฒนา ซึ่งมันทำให้เกิดกระบวนการทำงานร่วมกันของคนในกลุ่มต่าง ๆ ดังนี้
  • การเขียน examples
  • การเขียน automated tests ทั้ง unit test และ integration test
  • การ run automated test ให้ผ่านทั้งหมด
จนทำให้ function, story หรือ requirement มันเสร็จตามที่ตกลง

ผลจากพูดคุยใน workshop นี้ทำให้คุณ Declan Whelan และ Gojko Adzic และผองเพื่อน

ทำการสรุปขั้นตอนเพื่อสร้างความเข้าใจในเรื่อง Specification by Example (SbE) ขึ้นมาดังรูป atdd-01

ต่อมาคุณ Dan North ทำการอธิบายเรื่อง Behaviour Driven Development (BDD)

ซึ่งอธิบายในบทความเรื่อง Introducing BDD โดยเน้นไปที่ behaviour หรือพฤติกรรมการทำงาน มากกว่า test หรือการทดสอบ ด้วยการใช้ Given, When, Then เพื่ออธิบายการทำงานต่าง ๆ เช่น
  • Precondition
  • Action หรือ Trigger
  • Post-condition
BDD นั้นมีเป้าหมายเพื่อช่วยให้เราค้นพบสิ่งที่เราไม่รู้ ที่อยู่ในบริบทที่เราสนใจด้วย scenario และ example ต่าง ๆ จึงคำที่ใช้คือ should และ behaviour เนื่องจากคำว่า test มันใช้กับสิ่งที่เรารู้อยู่แล้ว

แต่ไม่ว่าจะเป็น ATDD, BDD, SbE ล้วนมีเป้าหมายและผลเดียวกันคือ

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

สิ่งที่น่าสนใจสำหรับ ATDD คือ

เมื่อเราพูดกับลูกค้า หรือ ทาง business แล้ว พบว่าไม่ค่อยเข้าใจเรื่อง Example และ Behaviour เท่าไร แต่เมื่อพูดคำว่า Acceptance tests ของแต่ละ function, story หรือ requirement กลับเข้าใจมากกว่า รวมทั้งยังทำให้ทีมรู้ขอบเขตของการพัฒนาและทดสอบ ซึ่งนั่นคือ เหตุผลสำคัญของการทำ ATDD

ลำดับของการทดสอบส่งผลต่อประโยชน์ที่จะได้รับจาก TDD นะ

$
0
0

kata-tdd

kata-tdd วันนี้ช่วงพักกลางวันจากงาน Conference JCSSE2016 ได้นั่งลองเขียน code ตามแนวคิด TDD (Test Driven Development) เพื่อทบทวนความเข้าใจในเรื่อง Small step (Increamental step) นั่นคือการสร้างระบบให้โตขึ้นอย่างต่อเนื่อง และ เสถียร ด้วยการเขียนชุดการทดสอบนั่นเอง โดยได้ฝึกตามบทความเรื่อง The Right Tests in The Wrong Order
สิ่งที่ได้เจอกับตัวเองคือ ถึงแม้ว่าชุดการทดสอบจะถูกต้องและสมเหตุสมผล แต่ถ้าลำดับของการทดสอบมันผิด ก็ส่งผลต่อประโยชน์ที่จะได้รับจาก TDD เช่นกัน

เริ่มต้นฝึกด้วยการการเขียนชุดการทดสอบขึ้นมา

ซึ่งเป็นแบบ Small step ไปเรื่อย ๆ จนกว่าจะได้สิ่งที่ต้องการ โดยเรียงลำดับของการทดสอบที่แตกต่างกัน ซึ่งได้ผลลัพธ์ที่น่าสนใจดังนี้ ตัวอย่าง เป็นการพัฒนา Stack ขึ้นมาใช้เอง
  • เป็น Stack ที่เก็บข้อมูลของตัวอักษร
  • โดยจะมีการทำงานต่าง ๆ เช่น
    • push(String)
    • pop(): String
    • peek(): String
    • size(): int
จากนั้นจึงเริ่มการพัฒนาด้วยชุดการทดสอบดังนี้
  1. เริ่มต้นจากการสร้าง Stack ว่าง ๆ ดังนั้นขนาดของ Stack มีค่าเป็นศูนย์
  2. ทำการ push ข้อมูล 1 ตัวไปยัง Stack ดังนั้นขนาดของ Stack มีค่าเพิ่มขึ้น 1
  3. ทำการ pop ข้อมูลออกจาก Stack ดังนั้นจะต้องได้ค่าที่ push ไปล่าสุด
  4. ทำการ pop ข้อมูลออกจาก Stack 1 ครั้ง ดังนั้นขนาดของ Stack จะลดลง 1
  5. ทำการดึงค่าล่าสุดใน Stack ด้วย peek()
เขียน code ตามแนวคิด Three rules of TDD ทำให้ได้ code ออกมาดังนี้ เริ่มจากชุดของการทดสอบ [gist id="a5b6f0e34e6f8c37843843acebfbc3ce" file="StackTest.java"] ทำให้ได้ production code แบบง่าย ๆ ดังนี้ [gist id="a5b6f0e34e6f8c37843843acebfbc3ce" file="StackString.java"]

แต่สิ่งที่ยังขาดอยู่คือ Stack ต้องรองรับการ push ข้อมูลที่มากกว่า 1 ตัว !!

คำถามคือ ถ้าเราต้องทำการเปลี่ยน code ใน class Stack จะกระทบเยอะไหม ? เช่นการเปลี่ยนชนิดข้อมูลของ input จาก String เป็น List ของ String
คำตอบที่ได้คือ เยอะมาก ๆ เกือบจะทั้งหมดยกเว้น size()
หมายความว่า ลำดับของการเขียน test ของเรานั้น มันไม่น่าจะถูกต้องแล้วนะ ถึงแม้ว่าจะเขียนแบบ Small step หรือค่อยเป็นค่อยไปแล้วก็ตาม !! มันยากดีนะ !!

ดังนั้นมาเริ่มต้นใหม่ดีกว่า

เพื่อลดผลกระทบของการเปลี่ยนแปลงโครงสร้างของข้อมูล เราจึงเปลี่ยนลำดับของการทดสอบใหม่ เริ่มจากการสร้างแต่ละ function ของ Stack ให้มันเสร็จไปเลย โดยเริ่มจาก size() นี่แหละ อย่าเพิ่งไปสนใจ push, pop, peek มากนัก ดังนี้ สามารถเขียนชุดการทดสอบใหม่ได้ดังนี้ [gist id="a5b6f0e34e6f8c37843843acebfbc3ce" file="StackTest2.java"] ทำให้เกิด production code ดังนี้ [gist id="a5b6f0e34e6f8c37843843acebfbc3ce" file="StackString2.java"] จากการเปลี่ยนลำดับของการชุดการทดสอบ พบว่า การพัฒนา code ราบรื่นมากยิ่งขึ้น รวมทั้งยังพัฒนา code แบบ Small step อยู่ เพียงแต่เปลี่ยนแนวคิดและแนวทางในการแก้ไขปัญหาเท่านั้นเอง โดยวิธีการนี้จะค่อย ๆ แก้ไขปัญหาแต่ละอย่างให้สำเร็จก่อน จากนั้นจึงไปแก้ไขปัญหาอื่น ๆ ต่อไป

สุดท้ายแล้วอย่าลืมฟังเสียง feedback ที่ได้รับจาก code นะครับ (Listen the feedback from your code)

TDD จะมีประโยชน์มาก ๆ ถ้าแต่ละรอบของ Red-Green-Refactor มันสั้น รวมทั้งต้องรับฟัง feedback จากผลลัพธ์ที่ได้ในแต่ละรอบด้วย เพื่อทำให้เราเดินต่อไปได้อย่างถูกต้องและเหมาะสม
จงอย่ากลัวที่จะผิด จงอย่างกลัวที่จะพลาด แต่จงเรียนรู้จากความผิดพลาดเหล่านั้น จากนั้นลองนำแนวคิดและวิธีการอื่น ๆ มาใช้งาน
สิ่งที่ผมทำอยู่นั้นคือ การฝึกฝนเพื่อให้ชำนาญ แต่มันจะไม่มีประโยชน์อะไรเลย ถ้าคุณไม่นำประยุกต์ใช้งานกับ production code โดย code ของการฝึกอยู่ที่ Github::Kata Stack

สรุปผลการสำรวจเรื่องการใช้งาน Java และ เทคโนโลยีที่เกี่ยวข้องประจำปี 2016 จาก RebelLabs

$
0
0

java-00

java-00 ในปี 2016 นี้ทาง RebelLabs ทำการสรุปผลสำรวจเรื่องการใช้งาน Java และเทคโนโลยีที่เกี่ยวข้อง ซึ่งแบ่งออกเป็น 3 ส่วน ดังนี้ ผมจึงได้ทำการสรุปบางอย่างที่น่าสนใจ ต่อการพัฒนาด้วยภาษา Java ไว้นิดหน่อยดังนี้

1. ข้อมูลทั่วไปของผู้ที่ตอบแบบสำรวจ

  • 54% เป็น Software developer
  • 67% เป็น project แบบ Full stack web application
  • มีเพียง 34% เท่านั้นที่เริ่มนำแนวคิด Microservice มาใช้ในการพัฒนาระบบ
  • ภาษาบน JVM ที่ใช้กันเยอะก็คือ Java 93% ส่วน Groovy และ Scala นั้นใช้งาน 3% และ 2% ตามลำดับ
  • 71% มีการนำ Agile มาใช้สำหรับทีมพัฒนา

2. Java SE ที่ใช้สูงสุดคือ Java 8 ถึง 62%

ส่วน Java SE 7 ก้ลงไปตามลำดับ แสดงแนวโน้มตั้งแต่ปี 2012 ดังรูป java-version-adoption-trend

3. Java EE นั้นพบว่ามีการใช้งานไม่เยอะ แถมคนไม่ใช้เยอะกว่าอีก

java-ee-breakdown

4. Web framework ยังคงเป็น Spring MVC และ Spring Boot ตามลำดับ

web-frameworks-breakdown

5. ส่วน IDE นั้นทาง IntelliJ IDEA สามารถแซงหน้า Eclipse ไปแล้ว

intellij-idea-overtakes-eclipse

6. ในเรื่องของ Build tool แน่นอนว่า Apache Maven ยังได้รับความนิยม

ส่วน Gradle ก็เริ่มโตขึ้นมา แต่ Apache Ant น่าจะเลิกใช้กันได้แล้วนะ build-tools-usage-through-years

7. มาดู Application Server กันบ้าง Apache Tomcat กินขาด

app-servers-clash

8. Version Control นั้น Git ทิ้ง SVN แบบไม่เห็นฝุ่นแล้วนะ

ใครยังใช้ Git ไม่เป็นก็ไปฝึกเถอะนะ vcs-trends

9. ในเรื่องของ Database ยังคงเป็น Oracle และ MySQL ตามลำดับ

databases-breakdown

10. ในการ build/compile/deploy ในแต่ละครั้งใช้เวลาเท่าไรกันบ้าง ?

มันคือ Waste time ที่ต้องสูญเสียไป ซึ่งมันส่งผลต่อ productivity และเวลาในการพัฒนา please-use-jrebel-to-eliminate-redeploys

11. ปิดท้ายด้วย Continuous Integration Server ยังคงเป็น Jenkins เจ้าเดิม

ci-servers-spread

ทำความเข้าใจกับ Legacy code ด้วยการเขียน Test สิ

$
0
0

legacy-code

legacy-code พอดีมีโอกาสแลกเปลี่ยนแนวทางในการจัดการ Legacy code จึงทำการสรุปสิ่งที่พูดไปไว้นิดหน่อย
Legacy code คือ code ที่ไม่มี Test ซึ่ง Test คือชุดการทดสอบแบบอัตโนมัตินะ
คำถาม ถ้าต้องการจะแก้ไข และ เพิ่มเติมอะไรเข้าไปยัง Legacy code ล่ะ จะต้องทำอย่างไร ? คำตอบคือ ต้องทำความเข้าใจกับมันก่อนสิ อ้างอิงตามเอกสารก็คงไม่ได้ เพราะว่าไม่เคยตรงกับ code จริง ๆ เลย แล้วจะทำไปทำไม ? ทำให้มี หรือ ทำให้ดี ?

เมื่อเอกสารเชื่อถือไม่ได้ ดังนั้นก็ต้องเชื่อ code นะสิ

ดังนั้นอ่านและทำความเข้าใจ code กันดีกว่า การทำความเข้าใจ code ของ programmer ก็ไม่ยาก เริ่มต้นด้วยการ debug หรือเรียกว่า Debug programming !! โดยการ debug มันมีหลายรูปแบบแตกต่างกันไป เช่น
  • ใช้ debug tool ผ่าน IDE
  • ใช้การ print ค่าต่าง ๆ ออกมาทาง console
  • ใช้การดูผลจากข้อมูลใน database
  • ใช้การส่ง mail
  • และอื่น ๆ อีกมากมาย
แน่นอนว่า มันไม่สนุกเลย !!

ดังนั้นขอแนะนำวิธีการที่ดีกว่า คือ การเขียน Unit test

แทนที่จะทำการ debug เพื่อดูการทำงานของ code อย่างเดียว ก็มีเขียน Unit test เพื่อตอบคำถามต่าง ๆ ที่เราต้องการดีกว่า น่าจะทำให้ชีวิตดีขึ้นกว่าเดิม ทำไมต้องเริ่มต้นด้วย Unit test ล่ะ ? Programmer ส่วนใหญ่จะคิดว่า Legacy code มันต้องมีจำนวนบรรทัดเยอะแน่ ๆ เป็นพัน เป็นหมื่น เป็นแสน มาบอกให้เขียน Unit test แล้วจะเริ่มกันตรงไหน ? จะทดสอบตรงไหน ? จะทดสอบอะไร ? มันเป็นไปไม่ได้หรอกนะ ยังไม่พอ code เหล่านี้มันไม่พร้อมต่อการเขียน Unit test ด้วยซ้ำ ลองคิดใหม่ ไม่มี code อะไรหรอกที่ทดสอบไม่ได้ (ยกเว้น code หาย !!) มันต้องมีการทดสอบสัก level ล่ะที่สามารถทดสอบได้ ทั้ง unit, component, integrate, system เป็นต้น ดังนั้นเราสามารถเขียน test เพื่อครอบคลุมการทำงานส่วนต่าง ๆ

แต่ก่อนที่จะเขียน Test ต้องเรียนรู้สิ่งเหล่านี้ก่อน

  • Input ที่ต้องใช้งานเป็นอย่างไร ?
  • Output ที่สร้างหรือส่งออกมาเป็นอย่างไร ?
  • ข้อมูลต่าง ๆ ที่ทำให้การทำงานสำเร็จคืออะไร ?
  • ข้อมูลต่าง ๆ ที่ทำให้การทำงานผิดพลาดคืออะไร ?
  • มี dependency อะไรบ้าง เช่น function/method, database, service และ system เป็นต้น
  • มันจะเกิดผลกระทบต่ออะไรบ้าง ?
  • และอื่น ๆ ที่คุณต้องเรียนรู้จากระบบที่ดูแล
มันคือการทำความเข้าใจการทำงานของระบบในส่วนนั้น ๆ นั่นเอง รู้นะว่ายาก แต่การ debug อยู่ตลอดเวลา มันไม่น่าจะเป็นเส้นทางที่ดีนะ อย่าผิดซ้ำที่เดิม !!

เมื่อเราเริ่มเขียนชุดการทดสอบแรก เราจะได้

  • ทำให้ programmer กล้าแก้ไข Legacy code มากขึ้น
  • ลดปัญหาจากการแก้ส่วนหนึ่ง แล้วกระทบอีกส่วนหนึ่ง
  • ลดปัญหาจากการแก้ bug แล้วเกิด bug อีกหลายตัว
  • ชุดของ Regression test ที่อาจจะทำงานแบบอัตโนมัติได้อีกด้วย
  • ทำให้การทดสอบง่าย และ เร็วขึ้น
แน่นอนว่า ในช่วงเริ่มต้นมันอาจจะเจ็บ และ ยาก บ่อยครั้งทำให้ programmer ส่วนใหญ่เลิกล้มความตั้งใจไป แต่ผมคิดว่า มันมีประโยชน์ตามมาที่คุ้มค่ากว่านะ
วันนี้ programmer เขียน test แล้วหรือยัง ? ถ้ายังก็เขียนสิครับ รออะไรกันอยู่

มาลอง Scale Elasticsearch ด้วย Docker Swarm Mode กันหน่อย

$
0
0

docker-000

docker-000 ติดตามข่าวสารเกี่ยวกับ Docker 1.12 มานิดหน่อย มีความสามารถใหม่ ๆ เพียบเลย นั่นคือเรื่องของ Docker Swarm Mode ทำให้เราจัดการได้ง่ายขึ้น ดังนั้นเพื่อให้เข้าใจจึงลองนำมาใช้งานกับ Elasticsearch กันดีกว่า เพราะว่า การลงมือทำน่าจะทำให้เราเข้าใจและแก้ไขปัญหาไปพร้อม ๆ กัน

โดย Software ที่ใช้งานคือ Docker for Mac 1.12 beta

docker-00

สิ่งที่ต้องการคือทำการ Scale Elasticsearch จาก 1 node ไปสัก 10 node กัน

ทุกอย่างทำบน Local หรือเครื่อง Mac นี่แหละนะ ยังไม่ได้ไปใช้ Cloud อะไรเลย
มีเป้าหมายเพื่อให้ Elasticsearch มี 10 node ให้ใช้บริการ โดยจัดการผ่าน Docker Swarm
ปล. ลอง 20 node แล้วเครื่องร้อนมาก ๆ !! และยังไม่ทำ Cluster ของ Elasticsearch นะ มาเริ่มกันเลย

1. ทำการสร้าง Swarm cluster ก่อน

ด้วยคำสั่ง [code] $docker swarm init [/code]

2. ทำการสร้าง Elasticsearch cluster ขึ้นมา 1 node ด้วย Docker service

ชื่อ service คือ elasticsearch ด้วยคำสั่ง [code] $docker network create -d overlay mynet $docker service create --name elasticsearch --network mynet --publish 9200:9200 elasticsearch [/code] ลองดูสถานะของ service เป็นอย่างไรด้วยคำสั่งดังนี้ รอไปจนกว่า REPLICAS จะเป็น 1/1 นะครับ ไม่นาน โดยจะทำการ join node ให้เองนะ [code] $docker service ls ID NAME REPLICAS IMAGE COMMAND 97dpatv5dvky elastic search 1/1 elasticsearch [/code] หรือดูสถานะของแต่ละ task ใน service ชื่อว่า elasticsearch ได้ [code] $docker service tasks elasticsearch ID NAME SERVICE IMAGE LAST STATE DESIRED STATE NODE eb5sbk8gi3mg8e9hwt4i7jshm elasticsearch.1 elasticsearch elasticsearch Running 5 minutes ago Running moby [/code] เมื่อทุกอย่างพร้อมลองเข้าไปดูหน้าแรกของ Elasticsearch หน่อยสิ จะ curl หรือเปิดหน้า web ก็ได้นะครับ docker-01

3. ทำการ Scale Elasticsearch ไปเป็น 10 node กันเลยดีกว่า

ด้วยคำสั่งที่ง่ายมาก ๆ คือ [code] $docker service scale elasticsearch=10 [/code] จากนั้นก็รอสักครู่ ใจเย็น ๆ หน่อยนะครับ รอให้ REPLICAS เป็น 10/10 เมื่อทุกอย่างพร้อมก็เป็นดังรูป ได้ Elasticsearch จำนวน 10 node มาให้ใช้แล้ว docker-02 โดยทุก ๆ task ที่เราเห็นนั้น มันคือ container นั่นเอง ตรวจสอบโดยใช้คำสั่ง [code] $docker ps [/code] แสดงดังรูป docker-03

4. ยังไม่พอนะถ้ามี node ใดก็ตาม fail หรือถูกลบไป

Docker จะทำการ restart ขึ้นมาให้เอง ดังนั้นลองมาลบ node ที่ 1 กัน ด้วยคำสั่ง [code] $docker rm -f d0d128565d3e [/code] ลองไปดูค่า REPLICAS จะเหลือ 9/10 แต่เมื่อเวลาผ่านไปสักครู่จะกลับมาเป็น 10/10 ให้เองโดยอัตโนมัติ ในระหว่างที่รอ ให้ทำการ access มายัง Elasticsearch จะพบว่าชื่อ node จะเปลี่ยนไป นั่นแสดงว่า Docker Swarm มี Load balance ในตัวให้นั่นเอง แสดงดังรูป docker-04

ด้วยความสามารถพื้นฐานต่าง ๆ เหล่านี้

มันทำให้เราจัดการ service ต่าง ๆ บน Cluster ด้วย Swarm Mode อย่างง่ายดาย ดูแล้วชีวิตน่าจะดีขึ้นมาก ส่วนรายละเอียดไว้ไปอ่านเพิ่มเติมในเอกสารต่อไปสำหรับ Docker Swarm Mode docker-05

ปล. ถ้าอยากลบ service ก็ใช้คำสั่ง

[code] $docker service scale elasticsearch=0 [/code] หรือถ้าต้องการลบ service ทิ้งไปเลยใช้คำสั่ง [code] $docker service rm elasticsearch [/code] Reference Websites https://blog.docker.com/2016/06/docker-1-12-built-in-orchestration/ https://medium.com/@LachlanEvenson/15-minutes-with-docker-swarm-mode-e6c38b9dafa0#.v9tovb8g7

Docker Swarm Mode :: Load balance มันทำงานอย่างไร ?

$
0
0

docker-web-00

docker-web-00 จาก blog เรื่อง มาลอง Scale Elasticsearch ด้วย Docker Swarm Mode กันหน่อย  คำถามที่น่าสนใจสำหรับการเริ่มต้นใช้งาน Docker Swarm Mode คือ
  • ถ้ามีหลาย ๆ container แล้วตอนทำงานจริง ๆ มันทำงานบน container ไหน ?
  • ที่บอกว่ามี Load balance มันทำงานจริง ๆ หรือไม่ ?
  • Load balance ทำงานแบบไหน ?
ดังนั้นลองมาหาคำตอบกันหน่อย

เริ่มด้วยการสร้างระบบ web application อย่างง่ายด้วยภาษา Go ขึ้นมา

โดยทำการแสดง Hostname หรือ ชื่อเครื่องออกมาเท่านั้นเอง เมื่ออยู่ใน Docker มันก็คือ container id นั่นเอง [gist id="9e00b841ece6447da36237646940bb41" file="hello.go"] ทำการ compile และทดสอบดูก่อนนะ ว่าทำงานตามที่คาดหวังหรือไม่ จากนั้นทำการสร้างไฟล์ Dockerfile ขึ้นมา เพื่อกำหนดขั้นตอนการทำงานต่าง ๆ ดังนี้ [gist id="9e00b841ece6447da36237646940bb41" file="Dockerfile"] สร้าง image ชื่อว่า web ด้วยคำสั่ง [code] $docker build -t web . [/code]

ทำการ setup Swarm Mode กัน

[code] $docker swarm init [/code] เมื่อทุกอย่างพร้อมก็สร้าง service ใช้กันเลย โดย service ชื่อว่า hello-web [code] $docker service create --publish 8080:8080 --name hello-web web [/code] ลองทดสอบการทำงานผ่าน curl หรือเปิด browser ก็ได้ [code] $curl http://localhost:8080 ได้ผลการทำงานดังนี้ Hello world, I'm running on <container id> [/code]

ทำการ Scale ให้ service ชื่อว่า hello-web มีสัก 10 เครื่อง ด้วยคำสั่ง

[code] $docker service scale hello-web=10 [/code] ต่อมาทำการยิงแบบรัว ๆ ผ่าน curl ได้ผลการทำงานเป็นดังรูป ซึ่งตอบคำถามได้หมดเลย เมื่อยิง request ไปยัง http://localhost:8080 พบว่า
  • แต่ละ request จะกระจายไปยัง container ต่าง ๆ
  • แสดงว่า Load balance ทำงานจริง ๆ
  • จากรูปด้านล่างจะพบว่า Load balance ทำงานแบบ Round-robin
docker-web-01 ต่อไปถ้าเอามา Scale พวก Microservice น่าจะง่ายดีนะ และมีคำถามมากมายจาก Slide เรื่อง What’s New in Docker 1.12 ? ไว้ศึกษากันต่อไป มันเยอะจริง ๆ Code ตัวอย่างอยู่ที่ Github::Up1

สรุปเรื่องของ Code Quality จาก Code Climate

$
0
0

code-quality-00

code-quality-00 นั่งดู VDO เรื่อง Code Quality Lessons Learned จาก CodeClimate.com ตั้งคำถามที่น่าสนใจเกี่ยวกับ Code Quality ไว้ดังนี้
  1. Code Quality คืออะไร ?
  2. ใช้อะไรวัดค่าความซับซ้อนของ code ?
  3. ทำไม code ของ project เก่า ๆ ถึงดูแลยากนักล่ะ ?
  4. ขนาดของ code ในแต่ละ Pull request สำหรับการ review ควรเป็นเท่าไรดี ?
  5. เมื่อไรที่ code แย่ ๆ ไม่ใช่ปัญหา ?
  6. อะไรบ้างที่เป็นตัวขัดขวาง Clean code ?
เท่านี้ก็น่าสนใจแล้ว จึงทำการสรุปไว้นิดหน่อย ส่วนตัวเต็ม ๆ ลองไปฟังจาก VDO ได้ครับแค่ 1 ชั่วโมงเอง

1. Code Quality คืออะไร ?

สิ่งที่ตรงข้ามกับ Code Quality คือ Legacy code ซึ่งมีความหมายมากมาย เช่น
  • Code ที่เขียนจากคนอื่น ๆ
  • Code ที่เขียนจากตัวเราเองเมื่อ 2 สัปดาห์ก่อน
  • Code ที่ไม่มี test
สิ่งที่น่ากลัวมาก ๆ สำหรับ Code Quality คือ มันมีความหมายมากมายเช่นกัน ดังนั้นสิ่งที่ทีมต้องระวังอย่างมากคือ เมื่อพูดถึง Code Quality แล้วหมายถึงอะไรกันแน่ ดังนั้นควรต้องตกลงกัน ต้องพูดคุยกัน เพื่อให้เข้าใจตรงกัน เช่น
  • Code ที่อ่านง่าย เข้าใจง่าย
  • Code ที่มีการทดสอบที่ดี
  • Code ที่มีชุดการทดสอบครอบคลุม
  • Code ที่ไม่มี bug
  • Code ที่ทำการ refactor มาแล้ว
  • Code ที่มีเอกสารอธิบายชัดเจน
  • Code ที่สามารถขยายเพิ่มได้ง่าย
  • Code ที่ทำงานได้อย่างรวดเร็ว
พูดคุยและตกลงกันภายในทีมให้เรียบร้อยนะ เพราะว่า นั่นคือเป้าหมายของทุกคนในทีม ซึ่งมีคำพูดที่น่าสนใจคือ
Any code less decomposed than mine is a mess. Any code more decomposed.
นั่นคือ code ที่เอาทุกสิ่งทุกอย่างมารวมกันไว้ในที่เดียว หรือพวก God class/method ทำให้เกิด Spaghetti code ก็ไม่ใช่สิ่งที่ดี หรือ code ที่แยกการทำงานต่าง ๆ ออกจากกัน มากจนเกินไป เราจะพบได้จากระบบที่นำเอา Design pattern มาใช้งานตั้งแต่แรกเริ่ม ซึ่งเราเรียกว่า over-engineering ก็ไม่ใช่สิ่งที่ดี ดังนั้นแต่ละระบบล้วนแตกต่างกัน ต้องปรับเปลี่ยนให้เหมาะสมกันไป

2. ใช้อะไรวัดค่าความซับซ้อนของ code ?

และใช้ตัวชี้วัดอะไรบ้าง เช่น ทีมลองตัดสินใจร่วมกันนะครับ ซึ่งอย่างน้อยให้ใช้ LOC มาเป็นตัวชี้วัด เช่น ในแต่ละ class/method ควรไม่เกินกี่บรรทัดดี ?

3. ทำไม code ของ project เก่า ๆ ถึงดูแลยากนักล่ะ ?

เนื่องจาก code แย่ ๆ มันถูกสร้างออกมาอย่างต่อเนื่องไงล่ะ เริ่มจากแรงกดกันจากส่วนต่าง ๆ ทั้งจากภายนอกและภายใน รวมทั้งสิ่งเล็ก ๆ ที่เรียกว่า Deadline ทำให้นักพัฒนาทุกคนสนใจแต่ ทำให้เสร็จ ทำให้เสร็จ ทำให้เสร็จ โดยไม่ได้สนใจ และ ใส่ใจใน code เลยว่าดีหรือไม่ และ code เหล่านั้นมันกลับทำให้ project พัฒนาช้าไปกว่าเดิม !! และจะอยู่ในวงจรนี้ไปเรื่อย ๆ แสดงดังรูป code-quality นั่นคือเมื่อเวลาผ่านไป Technical Debt ก็ยิ่งมากขึ้น รวมทั้ง Domain หรือ Business ก็เปลี่ยนไปเรื่อย ๆ ทำให้ code มีจำนวนสูงขึ้น Code ที่ไม่ใช้งานก็เยอะขึ้น เป็นแบบนี้ไปเรื่อย ๆ ทำให้ code เหล่านี้ดูแลได้ยากขึ้นเรื่อย ๆ ดังรูป code-quality-02 จากปัญหาเหล่านี้เราจะทำอย่างไรดีล่ะ ? เพื่อทำให้ code หรือระบบของเรามันดีขึ้น ซึ่งมีให้เลือก 2 แบบคือ
  1. Big design คือ คิดใหม่ ทำใหม่ ออกแบบใหม่ เขียนใหม่หมดเลย !!
  2. Iterative design คือ ค่อย ๆ ปรับเปลี่ยน ค่อย ๆ แก้ไขไปเรื่อย ๆ ซึ่งให้นำแนวคิด The Boy Scout Rule มาใช้

4. ขนาดของ code ในแต่ละ Pull request สำหรับการ review ควรเป็นเท่าไรดี ?

นั่นคือในการ review code แต่ละครั้งนั้น จำนวน LOC ควรเป็นเท่าไรดี ? จากบทความเรื่อง 11 proven practices for more effective, efficient peer code review อธิบายไว้ว่า ยิ่ง Pull request มีขนาดใหญ่มาก ยิ่งหา issue/bug ต่าง ๆ ได้น้อยลง ดังนั้นคำแนะนำคือ ในการ review code แต่ละครั้ง LOC ไม่ควรเกิน 400 บรรทัดนะ ซึ่งเป็นการ review code โดยใช้คน ไม่ได้ใช้เครื่องมือ นั่นหมายความว่า คนเรามีข้อจำกัดนะ ยิ่ง code เยอะ ก็ไม่อยากจะ review กัน !!

5. เมื่อไรที่ code แย่ ๆ ไม่ใช่ปัญหา ?

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

6. อะไรบ้างที่เป็นตัวขัดขวาง Clean code ?

ซึ่งทำให้เกิด code ที่แย่ ๆ ขึ้นมามากมายขนาดนี้ !! เริ่มด้วยการขาดความสนใจ ขาดความใส่ใจในสิ่งที่กำลังทำ ต่อมาคือ ขาดความรู้และความสามารถ บางครั้งเราไม่รู้ด้วยว่า สิ่งที่เราทำไปนั้นเป็นสิ่งที่ไม่ดี บางครั้งเราไม่รู้ด้วยซ้ำว่า จะแก้ไขอย่างไร และบ่อยครั้งที่ requirement เปลี่ยนบ่อยมาก ๆ ดังนั้นเราก็ทำให้มันเสร็จ ๆ ไปเถอะ เดี๋ยวก็เปลี่ยนแปลงอีก ซึ่งมันกลายเป็นสาเหตุหรือข้ออ้างหลักสำหรับการสร้าง code แย่ ๆ เลยนะ !! จากบทความเรื่อง Why do teams fail to sustain code quality? อธิบายสาเหตุของ code ที่ซับซ้อน แน่นอนว่า มันยากต่อการดูแล และ ง่ายต่อการเกิด bug อย่างมาก แสดงดังรูป code-quality-03 แต่สาเหตุหลักของ Code แย่ ๆ คือ ความกลัว (Fear) กลัวที่จะไม่ทัน กลัวที่จะโดนด่า กลัวที่แก้ไขไปแล้ว จะทำให้ระบบทำงานไม่ได้ ทั้งที่รู้และไม่รู้ กลัวที่แก้ไขไปแล้ว จะทำให้ตัวเองมีภัย กลัวที่จะ ... ดังนั้นมาลดความกลัวเหล่านี้กันเถอะ เช่น
  • Automated testing
  • Operational metrics
  • Code review
  • Static analysis
  • Pair programming

สุดท้ายแล้ว

ยังมีอะไรให้เรียนรู้อีกมากมาย ยังมีอะไรให้ปรับปรุงอีกมากมาย ดังนั้น เรื่องของวินัย เรื่องของความสามารถ เรื่องของอารมณ์และความรู้สึกร่วม มันต้องมาและไปพร้อม ๆ กัน
วันนี้เราเรียนรู้อะไรบ้างแล้วหรือยัง ? วันนี้เราปรับปรุงความสามารถให้ดีขึ้นแล้วหรือยัง ? วันนี้เราเขียน code แล้วหรือยัง ?
Viewing all 2000 articles
Browse latest View live