Tag Archives: xcode

XCode Font

ตั้งแต่ Swift เกิดขึ้นมา มันก็รองรับ Unicode ตั้งแต่แรก ดังนั้นแล้ว เราก็สามารถที่จะประกาศตัวแปร ด้วยตัวอักษรภาษาไทย หรือจะใช้ emoji ก็ได้ ดังเช่น

emoji_thai

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

thai_befor1

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

font

ผมเลือกที่จะสร้าง theme ขึ้นมาใหม่จาก theme basic เดิม แล้วก็เปลี่ยน font ให้มีขนาดใหญ่ขึ้น แต่อย่างไรก็ตามผมก็พบว่าตัวอักษรภาษาไทย มันก็ยังไม่ชัดอยู่ดี

thai_before2

จากรูปจะเห็นว่า แม้ว่าจะปรับฟ้อนต์ให้มันใหญ่ขึ้นมันก็ยังอ่านยาก และยิ่งเขียนโปรแกรมใน Macbook ที่มีหน้าจอ 13 นิ้ว การเพิ่มขนาดตัวอักษรให้ใหญ่ขึ้นนั้น จะทำให้เรามองเห็นโค้ดได้น้อยบรรทัดลง มันก็ทำให้เราต้องเลื่อน scroll บ่อยขึ้น ซึ่งผมว่ามันลำบากมากกว่าเดิม ต้นตอของปัญหาที่เกิดขึ้นก็คือแม้ว่า Xcode จะใช้ฟอนต์ Menlo ที่อ่านง่ายๆและมองได้นานๆ แต่เนื่องตัวอักษรภาษาไทยในฟ้อนต์ Menlo ไม่มี ดังนั้น  Xcode ก็จะเลือกใช้ฟ้อนต์อื่นแทน และนั่นก็คือ Ayutaya ซึ่งมันไม่เหมาะสำหรับการเขียนโปรแกรมเลย

ทำยังไงดี ?

อันดับแรกที่ผมพยายามจะทำก็คือการเปลี่ยน font ซึ่งก็ได้ลองเปลี่ยนดูหลายๆแบบ เช่น ลองใช้ Monaco ซึ่งเป็นฟ้อนต์เก่าที่  Xcode เคยใช้ตั้งแต่ version 3 หรือโหลดฟ้อนต์ที่เค้าว่าดีสำหรับการเขียนโค้ดเช่น DejaVu , Consolas มาลองใช้งาน แต่ปัญหามันก็ยังเหมือนเดิมคือ ภาษาไทย มันก็ยังแสดงผลด้วยฟอนต์ Ayuthaya อยู่ดี อย่างรูปด้านล่างคือเปลี่ยนใช้ฟ้อนต์ Monaco

mono

จากการเปลี่ยนฟอนต์เล่นๆไปๆมา ก็พบว่า ฟ้อนต์ภาษาไทย จริงๆมันเปลี่ยนได้ แต่มันจะเปลี่ยน ก็ต่อเมื่อฟ้อนต์นั้นรองรับภาษาไทยมาตั้งแต่แรกเลย อย่างเช่น Thonburi

thonburi

เท่าที่ลองเปลี่ยนไปมาดูหลายๆฟ้อนต์ก็พบว่า Thonburi นี่แหละอ่านง่ายดี  แต่ปัญหาใหม่คือ .. ผมไม่ชอบตัวภาษาอังกฤษ ของฟ้อนต์ Thonburi เลย ให้ตายเหอะ .. ดูๆแล้วมันไม่เหมาะกับเขียนโปรแกรมเลย

อยากให้ฟ้อนต์ภาษาอังกฤษเป็น menlo ส่วนภาษาไทยเป็น thonburi งั้นสร้างฟ้อนต์เองเลยดีไม๊ ? … แต่มานั่งคิดๆก็รู้สึกว่า สร้างฟ้อนต์ใหม่มันเหมือนเป็นการ ขี่ช้างไล่จับตั๊กแตนไปหน่อย แล้วมันจำเป็นถึงต้องสร้างฟ้อนต์ใหม่เพื่อแก้ปัญหาภาษาไทยใน XCode อ่านยาก ขนาดนั้นเลยเหรอ ?

จริงๆแล้วปัญหามันคืออะไร ..

ผมพบว่าปัญหามันคือ ถ้าเลือกใช้ฟ้อนต์ที่ไม่รองรับภาษาไทย .. มันจะแสดงด้วยฟ้อนต์ Ayuthaya  งั้นถ้าเราสามารถเปลี่ยนให้มันเป็นฟ้อนต์อื่นแทน Ayuthaya ได้ละ .. มันก็น่าจะแก้ปัญหาได้เช่นกันใช่ไหม ?

YES !!!! That’s right.

ผมนั่ง search google เพื่อหาวิธีการไขอยู่นาน จนกระทั่งพบว่า เราสามารถแก้ไข font – default ของ mac ได้ นั่นก็คือเข้าไปแก้ไขที่ไฟล์ DefaultFontFallbacks.plist ซึ่งจะอยุ่ในโฟลเดอร์

/System/Library/Frameworks/ApplicationServices.framework/Frameworks/

เมื่อเปิดไฟล์ขึ้นมา ให้หา monospace และเพิ่ม

(
( “th”, “Thonburi” ),
),

ต่อท้าย “Monaco” ดังที่แสดงในรูป

edit_font

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

จากนั้นก็ Save เสร็จแล้วก็ปิดและเปิด XCode ใหม่ ก็จะพบว่า ภาษาไทยแสดงด้วยฟ้อนต์ Thonburi แล้ว

thai_after1

เพียงเท่านี้เราก็ยังได้ฟ้อนต์ Menlo ที่อ่านง่ายเหมาะกับการเขียนโค้ด และใช้ฟ้อนต์ภาษาไทย Thonburi ที่อ่านง่ายกว่าฟ้อนต์ Ayuthaya เมื่อเปรียบเทียบกัน ก็จะยิ่งเห็นความแตกต่าง

befor_after

เห็นได้ชัดเลยว่า ภาษาไทย อ่านง่ายมากขึ้น และภาษาอังกฤษสำหรับเขียนโค้ด ก็ยังอ่านง่ายเหมือนเดิม

ก็ลองไปปรับเปลี่ยนกันดูนะครับ ถ้าใครไม่ชอบ Thonburi จะเปลี่ยนเป็นอย่างอื่นก็ตามใจเลยครับ และก็ก่อนแก้ไข แนะนำว่าควรจะ backup ไฟล์เดิมก่อน เผื่อว่าทำอะไรผิดพลาด

Happy Coding ครับ 🙂

Chapter 0

หนังสือที่ผมได้เขียนไปนั้น ได้เริ่มเมื่อประมาณปี 2012 หรือ 2 ปีที่แล้ว เนื้อหาบางอย่างจึงได้ล้าสมัยไป ทำให้ผู้ที่เริ่มศึกษาการเขียนโปรแกรมด้วยภาษา Objective-C อาจจะเกิดความสับสนได้ โดยเฉพาะเรื่องจัดการหน่วยความจำ ที่ได้เปลี่ยนมาใช้ ARC ทำให้โค้ดของโปรแกรมในบทแรกๆไม่สามารถ compile ด้วย XCode5 ได้ เพื่อแก้ปัญหาชั่วคราว ผมจึงได้ทำ video ขึ้นมาสอนการปรับโปรเจคให้ใช้ non arc เพื่อที่ผู้อ่านจะได้ compile โปรแกรมได้ และสามารถอ่านทำความเข้าใจเนื้อหา ในระหว่างช่วงที่หนังสือยังไม่เสร็จเรียบร้อยดี

Chapter 20: Debugging and Unit Testing (Part2)

Unit testing with XCTest

ถ้าหากหาทางป้องกันและการหลีกเลี่ยง bug ไว้ตั้งแต่เนิ่นๆ เวลาที่เสียไปกับการ debug ก็จะน้อยลง โปรแกรมมีประสิทธิภาพมากชึ้น หนึ่งในวิธีการป้องกันการเกิด bug คือการใช้ unit testing การทำ unit testing นั้นมีจุดประสงค์เพื่อใช้ทดสอบโค้ดบางส่วนของโปรแกรม เพื่อหาว่าโค้ดส่วนนั้นมีผลลัพธ์ตามที่คาดหวังหรือไม่ ซึ่งต้องอาศัยการเขียนโค้ดขึ้นมาทดสอบหรือที่เรียกว่า test cases ในปัจจุบันมีเฟรมเวิร์คสำหรับ unit testing ให้ใช้มากมายเช่น SenTestingKit , OCTest แต่หลังจาก XCode 5 ได้ออกมา ก็ได้เพิ่ม framework ใหม่เข้ามาสำหรับ unit testing ชื่อว่า XCTest ซึ่งเป็นเฟรมเวิร์คหลักของ Objective-C ในหัวข้อนี้เราจะเขียนโปรแกรมง่ายๆเพื่อใช้สำหรับหัดเขียน unit test โดยมีโค้ดดังต่อไปนี้

Program 20.4
Student.h

Student.m

เมื่อเขียนคลาสทั้งสองเสร็จแล้ว สิ่งที่จะทำต่อไปคือ unit test เพราะต้องการจะทดสอบก่อนว่าคลาสนี้ทำงานถูกต้องตามที่ต้องการ การใช้ unit test สามารถทำได้ด้วยเลือกเมนู File > New > Target … และเลือก Objective-C Unit Testing Bundle ดังรูป แต่ถ้าหากโปรเจคที่สร้างขึ้นมาเป็น iOS App หรือ Mac App จะมี unit test target มาให้เรียบร้อยแล้ว

unit1

เมื่อกด Next จะพบหน้าต่างให้ตั้งชื่อของ Target จากนั้นให้กด Finish ก็เป็นอันเสร็จสิ้นการสร้าง Unit Testing Target

unit2

ถ้าทุกอย่างเรียบร้อยก็จะเห็น folder ใหม่และไฟล์ต่างๆ พร้อมกับ target ใหม่ที่ได้เพิ่มเข้ามา

tartget

ในรูปจะเห็นว่ามีไฟล์ Program_20_4_Tests.m เมื่อเปิดไฟล์ Program_20_4_Tests.m ก็จะเจอโค้ดดังนี้

Program_20_4_Tests.m

ไฟล์ Program_20_4_Tests.m นี้ที่ใช้สำหรับเขียน test case จากโค้ดจะเห็นว่าเทสเคสนี้เป็นซับคลาสของ XCTestCase และมีเมธอดทั้งหมด 3 เมธอดด้วยกันคือ

setUp เมื่อสั่งให้ run test case เมธอดนี้จะถูกเรียกก่อนเสมอ ซึ่งมักใช้สำหรับการกำหนดค่าต่างก่อนจะเริ่มการทดสอบ
tearDown เป็นเมธอดที่จะเรียกหลังจาก test case ทั้งหมดได้ทำงานเสร็จสิ้น
testExample เรียกเมธอดนี้ว่าเป็น test case ซึ่งเมธอดนี้แสดงตัวอย่างวิธีการเขียน test case และเราสามารถประกาศ test case เองได้ โดยการขึ้นต้นชื่อเมธอดด้วย “test” เช่น testSum , testConnection , testValidEmail เป็นต้น และไม่ต้องกำหนดพารามิเตอร์และไม่ส่งค่าใดๆกลับไป

นอกจากไฟล์ Program_20_4_Tests.m แล้ว ยังสามารถเพิ่มไฟล์สำหรับเขียน Test Case โดยเลือกได้จากเมนู File > New > File .. และเลือก Objective-C Test case class

Run test cases

การสั่งให้ชุดทดสอบหรือ test case ทำงานนั้นสามารถทำได้โดยไปที่ Unit Test Navigation ดังรูป และคลิกที่รูปสามเหลี่ยมด้านท้ายของ test case ที่ต้องการ

run

จากนั้น test case จะเริ่มการทดสอบและ XCode จะแสดงผลลัพธ์จากการทดสอบดังนี้

test_fail

เทสเคสที่ได้ทำงานเสร็จสิ้นไป ได้แจ้งว่า testExample นั้นไม่ผ่านการทดสอบ พร้อมกับแสดงข้อความ failed – No implementation for “-[Program_20_4_Tests testExample]” ดังที่เห็นในรูป ไม่ต้องแปลกใจว่าทำไมชุดทดสอบนี้ไม่ผ่าน นั่นเป็นเพราะว่า testExample เรียกใช้ฟังก์ชัน XCFail ซึ่งจะให้ผลลัพธ์ว่าไม่ผ่านหรือเป็น fail เสมอ และในส่วนของ console จะแสดงผล ดังนี้

Test Suite ‘All tests’ started at 2014-02-18 11:02:37 +0000
Test Suite ‘Program 20.4 Tests.xctest’ started at 2014-02-18 11:02:37 +0000
Test Suite ‘Program_20_4_Tests’ started at 2014-02-18 11:02:37 +0000
Test Case ‘-[Program_20_4_Tests testExample]’ started.
/Program_20_4_Tests.m:31: error: -[Program_20_4_Tests testExample] : failed – No implementation for “-[Program_20_4_Tests testExample]”
Test Case ‘-[Program_20_4_Tests testExample]’ failed (0.000 seconds).
Test Suite ‘Program_20_4_Tests’ finished at 2014-02-18 11:02:37 +0000.
Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.000) seconds
Test Suite ‘Program 20.4 Tests.xctest’ finished at 2014-02-18 11:02:37 +0000.
Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.000) seconds
Test Suite ‘All tests’ finished at 2014-02-18 11:02:37 +0000.
Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.003) seconds

รายละเอียดของการทดสอบได้บอก จำนวนของ test case ที่ใช้ในการทดสอบ รวมถึงเวลาที่ใช้สำหรับการทดสอบแต่ละ test case และถ้าหากเทสเคสใด ไม่ผ่านก็ทดสอบก็แจ้ง fail เช่นเดียวกัน

Assert

ในการเขียน test case นั้นจะใช้ชุดคำสั่งที่เรียกว่า XCTAssert เช่น XCTFail ใน testExample คำสั่งเหล่านี้จะเป็นการทดสอบเงื่อนไขตามที่กำหนดเช่น XCTAssertFalse ใช้ทดสอบว่าเงื่อนไขนั้นต้องเป็นเท็จ หรือ XCTAssertEqual ใช้ทดสอบว่าค่าทั้งสองมีค่าเท่ากัน คำสั่ง XCTAssert ที่ใช้บ่อยๆ มีตามตารางดังต่อไปนี้

table

Your First Unit Test

ก่อนที่จะลงมือเขียน unit test แรก ให้ลบเมธอดทั้งสามที่มีอยู่แล้วออกไปเสียก่อน จากนั้นเขียน test case ใหม่ชื่อ testCreateStudent และมีโค้ดดังนี้

Program_20_4_Tests.m

ชุดทดสอบแรกที่เขียนคือ testCreateStudent จากโค้ดได้เรียกใช้ฟังก์ชั่น XCTAssertEqual เพื่อทดสอบว่าค่าของ score จะมีค่าเท่ากับ 60 ตามที่ได้กำหนดหรือไม่ ต่อมาใช้ XCTAssertEqualObject เพ่ือทดสอบว่าชื่อของนักเรียนที่ได้กำหนดให้กับอ็อบเจ็ก student ต้องเป็นค่าเดียวกัน เมื่อให้ test case ทำการทดสอบ ก็จะมักจะเกิดความผิดพลาดดังนี้

build error

สิ่งที่เกิดขึ้นคือโปรแกรมแจ้งเตือนว่ามีความผิดพลาด และความผิดพลาดนี้ไม่ใช่ข้อความแจ้งผลการทดสอบของ unit test เช่นที่ผ่านมา แต่กลับเป็นความผิดพลาดของการคอมไพล์ซึ่ง XCode ได้แจ้งว่า

Undefined symbols for architecture x86_64:
“_OBJC_CLASS_$_Student”, referenced from:
objc-class-ref in Program_20_4_Tests.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

หมายความว่า Program_20_4_Test ไม่รู้จัก symbols ที่ชื่อ _OBJC_CLASS_$_Student หรือพูดง่ายๆว่ามีการเรียกใช้คลาส Student จากไฟล์ Program_20_4_Test แต่กลับไม่เจอคลาส Student นั่นเอง สาเหตุที่ไม่เจอคลาส Student ก็เพราะว่าใน Unit Test Target ไม่ได้กำหนดให้คอมไพล์ไฟล์ Student เข้ามาใน target ด้วย จึงทำให้เกิดข้อผิดพลาด ดังนั้นสิ่งที่ต้องแก้ไขคือกำหนดให้  Unit Test Target นั้นคอมไพล์ไฟล์ Student ด้วย โดยการปรับที่ Build Phase และเพิ่มไฟล์ Student.m

setting

 

เมื่อทดสอบ test case อีกครั้งก็จะได้ผลลัพธ์ดังรูป

pass

สัญลักษณ์สีเขียวด้านหน้าของ test case ได้แสดงว่าการทดสอบผ่านเรียบร้อยดี ต่อไปจะเพิ่มคลาส Course เข้ามาในโปรแกรม ในขั้นตอนของการสร้างคลาสใหม่นี้ให้เลือกทั้งสอง Targets เพื่อจะได้ไม่เกิดปัญหาการคอมไพล์เหมือนที่ผ่านมา

target

คลาส Course ที่จะเขียนต่อไปนี้มีเมธอดให้นักเรียนลงทะเบียน , หาค่าเฉลี่ยคะแนนของนักเรียน , แสดงนักเรียนที่มีผลการเรียนดีที่สุด ,ค้นหานักเรียนจากชื่อได้, บอกจำนวนนักเรียนทั้งชั้น และสุดท้ายแสดงรายชื่อนักเรียนที่สอบผ่าน และมีข้อบังคับคือนักเรียนคนเดิมลงทะเบียนซ้ำไม่ได้, นักเรียนที่ผ่านสอบต้องมีคะแนนมากกว่าหรือเท่ากับ 50 คะแนน

Course.h

Course.m

ดูโค้ดผ่านๆ คลาสที่เขียนขึ้นมานี้น่าจะทำงานได้อย่างถูกต้อง แต่เพื่อความแน่ใจ ก็ต้องเขียนเทสเคสขึ้นมาทดสอบเมธอดต่างๆของคลาส Course ในครั้งนี้ให้สร้างไฟล์เทสเคสขึ้นมาใหม่ โดยเลือก template ของไฟล์เป็น Objective-C Test case class และตั้งชื่อว่า Course_Test จากนั้นเขียน test case ดังต่อไปนี้

Course_Test.m

เนื่องจากคลาส Course ต้องใช้ Student แทบจะทุกเมธอด ดังนั้นใน test case ที่เขียนขึ้นใหม่จึงได้ประกาศ Student เพื่อใช้ในการทดสอบทั้งหมด 5 อ็อบเจ็กด้วยกัน และเขียนส่วนของการสร้างอ็อบเจ็กไว้ที่เมธอด setUp

เทสเคสแรก testSearchStudent ใช้สำหรับทดสอบการหาอ็อบเจ็ก student จากชื่อที่กำหนด ถ้าหากไม่มีอ็อบเจ็กนั้นอยู่ในรายชื่อ สิ่งที่คาดหวังคือเมธอดต้องส่งค่า nil กลับมา

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

เทสเคส testMaxScore และ testAverage ใช้สำหรับการทดสอบคะแนนมากที่สุด และหาคะแนนเฉลี่ยของนักเรียน

และสุดท้าย testPassedStudent ไว้ทดสอบผู้ที่มีคะแนนผ่านเกณฑ์ที่กำหนด เมื่อเขียนเทสเคสเสร็จเรียบร้อย จากนั้นให้ทำการทดสอบ test case ที่ได้เขียนไป ก็จะพบกับผลลัพธ์ดังนี้

Test Case ‘-[Course_Tests testAverage]’ started.
/Course_Tests.m:78: error: -[Course_Tests testAgerage] : (([course averageScore]) equal to (0)) failed: (“nan”) is not equal to (“0”) – average score fail

Test Case ‘-[Course_Tests testPassedStudent]’ started.
/Course_Tests.m:97: error: -[Course_Tests testPassedStudent] : (([passed count]) equal to (4)) failed: (“3”) is not equal to (“4”) – passedStudent fail

Test Case ‘-[Course_Tests testSearchStudent]’ started.
/Course_Tests.m:51: error: -[Course_Tests testSearchStudent] : ((studentB) == nil) failed: “Weerapong : 65” – search fail

ผลของการทดสอบมี test case ที่ไม่ผ่านถึง 3 เคสด้วย โดยเคสแรก testAverage ได้แจ้งว่าทดสอบไม่ผ่านเพราะเกิดค่า “nan” ค่านี้จะเกิดขึ้นได้ก็ต่อเมื่อหารด้วย 0 เมื่อย้อนกลับไปดูเมธอด averageScore จะเห็นว่ามีข้อผิดพลาดคือ ในกรณีที่ไม่มีนักเรียนอยู่เลยจำนวนนักเรียนจะเป็น 0 ดังนั้นโปรแกรมจะหารด้วย 0 นั่นเอง การแก้ปัญหานี้คือให้ส่งค่า 0 กลับเมื่อ studentList ไม่มีอ็อบเจ็ก Student อยู่เลย

เทสเคสต่อมาคือ testPassedStudent ซึ่งได้คาดหวังผลลัพธ์ว่าจำนวนนักเรียนที่ผ่านสอบควรจะเป็น 4 แต่ผลการทดสอบแจ้งว่าเป็น 3 เมื่อพิจาณาจากโค้ดของเมธอด passedStudent จะเห็นว่าเงื่อนไข score > 50 ที่ใช้ในการเปรียบเทียบนั้นผิด ทำให้นักเรียนที่มีคะแนน 50 สอบตก เงื่อนไขที่ถูกต้องคือ score >= 50
ส่วนเคสสุดท้าย testSearchStudent สิ่งที่ต้องการคือหานักเรียนชื่อ Weera โดยผลลัพธ์ที่คาดหวังคือต้องไม่เจอนักเรียนคนดังกล่าว แม้ว่าโปรแกรมจะไม่เจอ Weera แต่จากผลการทดสอบก็ยังพบข้อผิดพลาด เพราะเมธอดได้พบนักเรียนชื่อ Weerapong เมื่อกลับไปดูโค้ด studentWithName: ก็จะเห็นว่า predicate ที่ใช้คือ @”name contains %@” นั้นไม่ถูกต้อง เพราะเป็นการหาชื่อที่มีส่วนใดส่วนหนึ่งประกอบด้วยคำที่กำหนด ดังนั้นเมื่อค้นหา Weera ก็จะได้ Weerapong ด้วย เพราะ Weerapong มีคำว่า “Weera” อยู่นั่นเอง เราควารแก้ไขเงื่อนไขให้เป็น @”name contains %@” โปรแกรมก็จะทำงานได้อย่างถูกต้อง

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

เมื่อให้ชุดทดสอบได้ทำงานอีกครั้ง ก็จะพบว่าเมธอดนี้ไม่ผ่านการทดสอบ การใช้ Unit Test นั้นอาจจะดูเป็นเรื่องไม่จำเป็น เพราะต้องเขียนโค้ดที่ใช้ทดสอบมากมายหลายอย่างด้วยกัน และยังต้องคิด test case เพื่อใช้ในการทดสอบ แต่การใช้ Unit Test นั้นช่วยป้องกันปัญหาความผิดพลาดของโปรแกรมในระยะยาวได้เป็นอย่างดี โดยเฉพาะเมื่อต้องเขียนโปรแกรมขนาดใหญ่ และมีโปรแกรมเมอร์หลายคนในโปรเจค  การใช้ Unit Test จะเป็นสิ่งช่วยป้องกันความผิดพลาดในโปรแกรมที่จะเกิดขึ้นได้เป็นอย่างดี

Summary

 

สิ่งที่ได้เรียนรู้ในบทนี้ แม้ไม่เกี่ยวกับภาษา Objective-C โดยตรง แต่ก็เป็นประโยชน์สำหรับการเขียนโปรแกรมอย่างแน่นอน เพราะนอกจากความรู้ความเข้าใจเกี่ยวกับภาษาแล้ว ยังต้องมีทักษะอย่างอื่นเช่นการ debug หรือการใช้ unit testing หนังสือเล่มนี้ไม่อาจจะอธิบายการใช้งานต่างๆได้หมดเช่น การใช้ lldb command ซึ่งมีประโยชน์อย่างมากในการ debug สำหรับผู้ที่สนใจสามารถศึกษาเพิ่มเติมได้จากเอกสารของโครงการ lldb โดยตรง

It just beginning not the end

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

สุดท้ายนี้มีคำพูดหนึ่งที่ สตีฟ จ็อบ ได้กล่าวตอนให้สุนทรพจน์แก่นักศึกษา Stanford University ที่จบใหม่ และผมก็จะขอนำคำพูดนั้นมาพูดกับคุณอีกครั้ง
“Stay foolish Stay hungry”

 

โหลด PDF ไปอ่านได้ครับ

ส่วน Source code ก็เช่นเดิม โหลดได้ที่ github