June 27, 2016

ทำให้ Helper function ใน XCTest บอกตำแหน่งที่ Fail

หลังจากที่เราเขียนโค้ด test ไปเรื่อยๆ จะพบว่าหลายๆ case ที่ทดสอบนั้นจะมี Assertion ที่คล้าย หรือซ้ำกันเกิดขึ้น ทำให้บางทีเราจำเป็นต้องตัดสินใจแยกออกมาเป็น function ย่อยๆ ให้แต่ละ case ได้เรียกใช้งานร่วมกัน แต่ปัญหาก็คือ เมื่อ Test Fail เกิดขึ้นใน function เหล่านั้น เราไม่สามารถบอกได้ว่า test function ไหน fail เพราะ Xcode ดันไป highlight error ใน helper function แทน แทนที่จะ highlight ใน function test ที่เราเขียน

ยกตัวอย่างเวลาเขียนเขียน test UI แล้วสิ่งหนึ่งที่เรามักต้องทำซ้ำๆ กันก็คือ การทดสอบว่า element นั้นๆ มัน appear ออกมาหรือยัง ซึ่งเราก็สร้างออกมาเป็น function แยกต่างหาก ดังโค้ดต่อไปนี้

June 18, 2016

เริ่มเขียน Unit Testing ด้วย Swift

เท่าที่เคยสนทนากับหลายคนเกี่ยวกับการเขียน Unit Testing มา พบว่ามีคนอยู่ 2 กลุ่ม คือ

กลุ่มที่ 1 ไม่พูดถึง :D
กลุ่มที่ 2 คือ คนที่เห็นคุณค่าของการเขียน test อยากเขียน test แต่ยังไม่เขียน เพราะไม่รู้จะเริ่มต้นยังไงดี บางคนเคยลองเริ่มต้นเองดูแล้วแต่ไม่สามารถจับทิศทางหรือเทคนิคได้ ก็เลยเลิกล้มไปในที่สุด

สำหรับคนกลุ่มที่ 2 ควรลองอ่านบทความนี้ดูครับ บทความนี้จะเสนอแนวคิดขั้นต้นในการเขียนโค้ดเพื่อให้เราสามารถ Test ได้

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

นี่คือ 4 เรื่องหลัก ที่เราต้องคิดถึงมันตลอดเวลาที่เราเขียนเทส และออกแบบ production code ของเรา

May 24, 2016

Monkey Test in iOS Project ให้ลิงลองเล่นแอพเราดูหน่อยซิ

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

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

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

ในฝั่ง Android นั้นมี ลิง ของตัวเองสำหรับทำ stress test มาให้แล้ว แล้วในฝั่ง iOS ล่ะ ? อันที่จริง Instruments ที่ติดมากับ Xcode นั้นสามมารถทำ stress test ได้ แต่มันไม่ได้ถูกออกแบบมาให้เราใช้งานได้อย่างตรงไปตรงมาสำเร็จรูปแบบเดียวกับที่ Android มีสักทีเดียว

วิธีที่เราจะใช้ทำ stress test กับ iOS แอพของเราก็คือการเขียนโค้ด javascript แล้วสั่งมันสุ่มวนทำ Interaction ต่างๆ บนหน้าจอไปเรื่อยๆ เท่านั้นเอง

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

โชคดีที่โลกนี้ยังไม่สิ้นหวังไปซะทั้งหมด เพราะนาย Jonathan Penn ได้เขียน Javascript ชุดนี้ให้เรานำมาใช้ใน Instruments ได้เลย ... เอาล่ะ มาลองใช้กันสักหน่อยว่าเป็นยังไง

May 05, 2016

ซ่อน API ที่ซับซ้อนด้วย Builder Pattern

สำหรับตอนนี้ เป็นการเอาเหล้าเก่าในขวดใหม่มาเล่าต่อ สำหรับใครที่เคยเขียนภาษา​ Java หรือ Groovy มาก่อน ก็จะคุ้ยเคยกับคลาสที่ลงท้ายด้วยคำว่า Builder กัน รวมถึงวิธีใช้งานคลาสเหล่านี้ด้วย

ทีนี้ถึงคราวของ Swift บ้าง เรามาลองออกแบบ Builder Class ด้วย Swift อย่างง่ายๆ กัน

บน iOS ก็มี API บางตัวเวลาเราจะใช้งานมันได้ ก็ต้องสร้างนั่นสร้างนี่ 2-3 ขั้นตอน กว่าเราจะรวมร่างให้มันกลายเป็นสิ่งที่เราต้องการได้ ยกตัวอย่างเช่น การแสดง Alert ขึ้นมาบนหน้าจอ ที่เวลาเราจะสร้าง Alert ขึ้นมาสักอัน เราจำเป็นต้องรู้ก่อน ว่าเราจะใช้ UIAlertController สำหรับกำหนด title, message และใช้ UIAlertAction สำหรับสร้างปุ่มบน Alert และ action ที่จะเกิดขึ้นตามมาหลังจากกดปุ่มนั้น พอสร้างเสร็จก็เพิ่มลงไปใน UIAlertController และสุดท้าย ก็สั่งให้ UIViewController แสดง UIAlertController ที่กำหนดค่าเรียบร้อยแล้วขึ้นมาบนหน้าจอให้ User เชยชม

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

March 27, 2016

เราจะสร้างประสบการณ์การขอสิทธิ์ (permission request) ในการเข้าถึงข้อมูลที่ดีให้แก่ผู้ใช้แอพได้อย่างไร?

อย่างหนึ่งที่จะทำให้ผู้ใช้ (user) รู้สึกหงุดหงิดเวลาใช้แอพของเราก็คือ การถูกถามขอสิทธิ์ (permission) ในการเข้าถึงข้อมูลสำคัญที่เป็นส่วนตัวของเรานั่นเอง ซึ่งสิทธิ์เหล่านี้ก็เช่นการขอเข้าถึง location service, camera, push notification, calendar, contact สาเหตุที่ขอก็เพื่อให้แอพสามารถทำงานได้อย่างเต็มความสามารถนั่นเอง แต่เมื่อไรก็ตามที่ผู้ใช้ไม่ให้สิทธิ์ที่แอพต้องการ แอพก็อาจทำงานได้ไม่เป็นไปตามที่ตั้งใจไว้ได้อย่างเต็มที่ และส่งผลให้แอปมีคุณค่าต่อผู้ใช้น้อยลง และสุดท้าย ผู้ใช้ก็ตัดสินใจลบแอปทิ้งในที่สุด :) 

ทำไมล่ะ? ลบทิ้งทำไม ลบทิ้งทั้งๆ ที่ยังไม่ได้ใช้ฟีเจอร์ที่ตั้งใจทำมาให้ใช้เลยเนี่ยนะ... น่าเศร้าใช่ไหม?

ส่วนใหญ่แล้ว Apple มักจะไม่ให้ขอสิทธิ์มั่วๆ อยู่แล้ว ถ้ามองในมุมของ iOS App เมื่อนักพัฒนาอัพโหลดแอพส่งขึ้นไปบน AppStore ก็จะมีเจ้าหน้าที่จาก Apple มาตรวจสอบแอพ รวมถึงตรวจสอบการร้องขอสิทธิ์ต่างๆ ว่าเหมาะสมหรือไม่ หากไม่เหมาะสมแอพนั้นจะไม่ได้รับอนุญาติให้ผู้ใช้คนอื่นดาวน์โหลดผ่าน AppStore ได้ ดังนั้นผู้ใช้ทางฝั่ง iOS ก็พอจะอุ่นใจได้บ้างว่า ที่แอพขอสิทธิ์เราไปน่ะ แอพได้เขียนอธิบายไว้ชัดเจน และไว้ใจได้แน่นอนว่าแอพจะไม่เอาข้อมูลเราไปใช้อย่างอื่นนอกจากที่เขียนบอกเราไว้แล้ว (ดังนั้นก่อนให้สิทธิ์ต่างๆ ควรอ่านให้ดีก่อนนะ)

การออกแบบหน้าจอการขอสิทธิ์ในการเข้าถึงข้อมูลส่วนตัวจากผู้ใช้นั้น ให้ focus อยู่ที่ 3 เรื่องหลักได้แก่ 1. เวลา, 2. บริบท (context) และ 3. ข้อความที่ใช้ขอสิทธิ์ เอาล่ะ มาดูกันว่าจะใช้ 3 สิ่งนี้ในการขอสิทธิ์ให้สำเร็จได้อย่างไร

March 06, 2016

Swift Lazy: เรามาขี้เกียจกันเถอะ

บทความนี้จะใช้ความขี้เกียจแสดงวิธีการเขียนโค้ดให้ดูดีมีประสิทธิภาพกันมากขึ้น โดยภาพรวมเราจะพูดถึง lazy variable และ lazy sequence

โจทย์
เรากำลังทำแอปที่ต้องแสดงรูป avatar ในขนาดที่ต่างๆ กันไป โดยเราจะมีขนาดหลักอยู่ 1 ขนาด และเมื่อใดก็ตามที่มีการเรียกใช้ avatar ในขนาดอื่น เราถึงจะ resize รูปเพื่อเอาไปใช้อีกที แบบนี้



December 23, 2015

รีวิว Apple Watch จากการใช้งานจริง คนแบบไหน ไลฟ์สไตล์แบบไหนจึงเหมาะกับ Apple Watch


ที่มา: http://news.iapplefan.com

เท่าที่คุยกับแฟน Apple หลายคน พบว่าแทบทุกคนยังลังเลอยู่ว่าจะซื้อ Apple Watch มาใช้ดีไหม แม้แต่ตัวผมเองก็ยังลังเล อาจเพราะ Apple เปิดตัวสินค้าได้ไม่น่าสนใจ และไม่รู้ว่าจะมีมันไปทำไม

ก่อนหน้านี้ผมสงสัย และลังเลอยู่นานมาก ว่าจะใช้ Apple Watch ดีไหม? ตามอ่านรีวิวหลายต่อหลายที่ สุดท้ายวิธีตอบข้อสงสัยที่ผมรู้สึกดีที่สุดในฐานะแฟน Apple คนหนึ่งก็คือ ซื้อมาใช้เองซะเลย ซึ่งหลังจากใช้ Apple Watch ไปได้สักพัก ก็คลายข้อสงสัยผมไปหลายอย่าง และต่อไปนี้คือคำตอบของคำถามที่ผมสงสัย รวมถึงคำถามต่างๆ จากคนรอบข้างด้วย ว่าทำไม ไลฟ์สไตล์ และนิสัยในการใช้งานแบบผมถึงรู้สึกว่าไม่มีปัญหาอะไรที่ใช้ Apple Watch

รีวิวนี้ เขียนโดยอิงจากไลฟ์สไตล์ และจริตส่วนตัวของผมโดยเฉพาะ ไม่ได้เปรียบเทียบกับยี่ห้ออื่น หรือความต้องการ ความชอบของคนอื่น ดังนั้นหากอ่านแล้วพบว่า มันไม่ใช่อย่างที่ผมรีวิวไว้ก็ไม่ใช่เรื่องแปลกอะไรครับ :)

September 18, 2015

Swift: Enums กับ Associated Values

ใน Objective-C เราสามารถอ้างถึงค่าของสมาชิกใน enum ได้ ซึ่งเราจะได้ integer กลับมา แต่ว่าด้วยฟีเจอร์ associated value ของ Enum ใน Swift นั้นทำให้เราสามารถกำหนดค่าที่ต่างชนิดกันได้ให้กับสมาชิกใน enum เช่น สมาชิกใน enum ตัวหนึ่งอาจเก็บค่าชนิด Integer ส่วนอันหนึ่งเก็บค่าชนิด String  และอีกอย่างหนึ่งก็คือค่าของสมาชิกใน enum ที่ประกาศเป็น associated value จะถูกกำหนดให้ตอนที่ค่าของ enum ถูกสร้างขึ้นมา ไม่ใช่ตอนประกาศ เพราะตอนประกาศเราจะประกาศแค่ชื่อ และชนิดข้อมูลที่เก็บเท่านั้น ส่วนตัวอย่างที่หลายที่มักหยิบยกมากัน ก็คือการนำไปใช้กับรูปแบบโค้ดที่ต้อง return ค่ากลับออกมาต่างชนิดกันนั่นเอง

ยกตัวอย่างโค้ดการทำงานของบัญชีธนาคาร ที่มีจำนวนเงินเก็บไว้จำนวนหนึ่ง และมี method ที่ใช้สำหรับถอนเงินออกมา โดยที่ ถ้าจำนวนเงินที่ต้องการถอนมีจำนวนมากกว่าเงินที่เก็บไว้ ก็จะ return error message string ออกมา แต่ถ้าหากจำนวนเงินสามารถถอนออกมาได้จริง ก็จะ return จำนวนเงินคงเหลือออกมา

ถึงตรงนี้เราจะพบว่าค่าที่ถูก return กลับออกมานั้นมี type ที่แตกต่างกัน อันหนึ่งเป็น String และอีกอันหนึ่งเป็น Integer เจอแบบนี้ เราสามารถใช้ enum เข้ามาช่วยได้โดยการออกแบบ enum เตรียมไว้ก่อนได้ดังนี้


August 23, 2015

iOS9 Introducting the Contacts Framework

iOS9 จะมาพร้อมกับวิธีการเข้าถึง Address Book แบบใหม่ผ่าน Contacts Framework โดยจุดที่น่าสนใจก็คือ Framework ตัวนี้จะช่วยเราให้รอดพ้นจากความน่าเบื่อของ AddressBook Framework ตัวเดิมไปได้สักที ผมเชื่อว่าหลายคนต้องเบื่อ และรู้สึกว่า AddressBook Framework มันยากเย็นและดูซับซ้อน อีกทั้งวิธีการใช้งานก็ดูจะไม่เข้ากันกับ Objective-C เอาซะเลย

ดึงรายชื่อจาก Contacts ทั้งหมดที่มี
มาเริ่มลองดึงรายชื่อจากสมุดรายชื่อเลยดีกว่า โดย import Contacts ข้ามาใช้งาน จากนั้น สร้าง func listAllContacts() แบบนี้


August 01, 2015

Swift Type inference กับการลดรูป Closure

Closures คล้ายกับ functions และ method มันคือ block ของโค้ดที่เราเรียกใช้มัน แต่ไม่ได้เหมือนกันซะทีเดียว เพราะ closure ไม่มีชื่อ และมีความสามารถบางอย่างต่างออกไป เช่นการ capture value ที่เกิดใน scope เดียวกัน (บทความนี้ไม่ได้พูดถึง)

สำหรับหลายคนเมื่อเห็น syntax ประมาณนี้จะเกิดความสงสัยว่า โค้ดแบบนี้มาจากไหน

myArray.sorted{$0 > $1}

ซึ่งบทความนี้จะเล่าถึงที่มาที่ไปของมัน เริ่มจากลองดูตัวอย่างจาก method sorted ของ Array กันครับ

func sorted(isOrderedBefore: (T, T) -> Bool) -> [T]

method นี้มี parameter  1 ตัวชื่อ isOrderedBefore ซึ่งเป็น function ที่รับ parameter 2 ตัวชนิด T (ชนิดของข้อมูลที่ array บรรจุอยู่)  และ return Bool กลับออกมา ซึ่ง method sorted จะ return Array ที่เรียงเสร็จแล้วกลับออกมาอีกที

จากนิยามของ method sorted เมื่อเราลองลองสร้าง function เพื่อใช้เป็น parameter ตามที่นิยาม (รับ parameter 2 ตัว และ return เป็น Bool) ดู ก็จะได้โค้ดออกมาแบบนี้


ลองรันโค้ดดูจะพบว่า ได้ array ที่เรียงกันตามตัวอักษรถูกต้อง โดยอิงตามกฎที่ว่า ใครมาทีหลัง ให้มาก่อน