ข้อดีของภาษา C# เมื่อเทียบกับภาษาอื่น ๆ ตอนที่ 12

ข้อดีของภาษา C# เมื่อเทียบกับภาษาอื่น ๆ ตอนที่ 12
ต้นไม้นิพจน์กับ API
ในตอนที่ผ่านมาได้พูดถึงข้อดีของภาษาซีชาร์ปที่มีคุณสมบัติ Expression Trees หรือ “ต้นไม้นิพจน์” ซึ่งเป็นข้อดีในภาษาซีชาร์ปที่ไม่พบในภาษาอื่น ๆ หลายภาษาอย่างเช่นภาษาซี หรือในภาษาจาวาสคริปต์ที่มีต้นไม้นิพจน์แบบย่นย่อ ไม่ใช่ต้นไม้นิพจน์เต็มรูปแบบอย่างที่เรากำลังพูดถึงอยู่ในขณะนี้
ประโยชน์ของต้นไม้นิพจน์มีหลายอย่าง หนึ่งในนั้นคือเมื่อท่านต้องการทำ Application Programming Interface (API) เช่นสร้างหรือใช้เฟรมเวิร์กหรือไลบรารีเพื่อให้โปรแกรมภายนอกสามารถเชื่อมต่อได้ง่าย ๆ ในรูป
บรรทัดที่ 3 แสดงตัวอย่างการใช้ต้นไม้นิพจน์เพื่อใช้งานเอพีอายของ เฟรมเวิร์ก Rhino.Mocks ซึ่งทำหน้าที่กำหนดว่า Experct รอรับเมธอด Process ที่ตัวแปร parser ซึ่งจะถูกเรียกให้ทำงานระหว่างการทดสอบโค้ด ไม่ใช่ถูกเรียกให้ทำงานในขณะนี้ในรูป
บรรทัดที่ 5-14 แสดงตัวอย่างโค้ดการใช้งานต้นไม้นิพจน์เมื่อทำงานกับไลบรารี Fluent NHibernate เพื่อการกำหนดค่าให้แก่ nHibernate โดยไม่ใช้ไฟล์ XML
บรรทัดที่ 3 แสดงตัวอย่างการใช้ต้นไม้นิพจน์เพื่อใช้งานเอพีอายของ เฟรมเวิร์ก Rhino.Mocks ซึ่งทำหน้าที่กำหนดว่า Experct รอรับเมธอด Process ที่ตัวแปร parser ซึ่งจะถูกเรียกให้ทำงานระหว่างการทดสอบโค้ด ไม่ใช่ถูกเรียกให้ทำงานในขณะนี้ในรูป
บรรทัดที่ 5-14 แสดงตัวอย่างโค้ดการใช้งานต้นไม้นิพจน์เมื่อทำงานกับไลบรารี Fluent NHibernate เพื่อการกำหนดค่าให้แก่ nHibernate โดยไม่ใช้ไฟล์ XML
สมมุติว่าเรามีเมธอดที่นำสตริงก์สองตัวมาผสมกันเพื่อให้เกิดสตริงก์ใหม่ด้วยการใช้ต้นไม้นิพจน์เพื่อทำเลมบ์ดาจะเขียนโค้ดได้อย่างที่เห็นในรูป M เมื่อโค้ดนี้ทำงานจะมีผลให้ตัวแปร combined มีค่าเป็น "oneTWO."
ส่วนบรรทัดที่ 9 ในรูป แทนที่เราจะใช้แลมบ์ดาเพื่อนิยามเมธอด เราอาจเขียนต้นไม้นิพจน์แทนก็ได้ โดยใช้วิธีอย่างที่เห็นในบรรทัดที่ 9 ของรูป
ส่วนบรรทัดที่ 9 ในรูป แทนที่เราจะใช้แลมบ์ดาเพื่อนิยามเมธอด เราอาจเขียนต้นไม้นิพจน์แทนก็ได้ โดยใช้วิธีอย่างที่เห็นในบรรทัดที่ 9 ของรูป
เมื่อสร้างต้นไม้นิพจน์แล้วเราสามารถเขียนโค้ดสั้น ๆ เพื่อตรวจสอบโครงสร้างของแลมบ์ดาได้โดยใช้โค้ดในรูป
เมื่อรันโค้ดในรูปแล้วจะได้ผลลัพธ์อย่างที่เห็นในรูปจะเห็นว่าด้วยการเขียนโค้ดเพียงเล็กน้อยเราสามารถตรวจสอบได้ว่าแลมบ์ดานี้มีพารามิเตอร์ทั้งหมดกี่ตัว ชื่ออะไรบ้าง และค่าส่งกลับของแลมบ์ดาเป็นชนิดข้อมูลอะไร เนื่องจากต้นไม้นิพจน์ในตัวอย่างนี้เป็นต้นไม้แบบไบนารี เราจึงเห็นการนำนิพจน์สองอันมาผนวกกัน โดยมีเมธอด String.Concat ทำหน้าที่นี้
อีกตัวอย่างหนึ่งของประโยชน์ของต้นไม้นิพจน์คือเราสามารถนำมันมาอ้างถึงชื่อเมธอดแทนที่การอ้างโดยใช้สตริงก์ ยกตัวอย่างเช่นในรูป
บรรทัดที่ 3 คือการอ้างถึงชื่อเมธอดโดยใช้สตริงก์ที่มีข้อเสียคือตอนเปลี่ยนชื่อเมธอดเราต้องพิมพ์ใหม่ทุกที่หรือใช้เครื่องมือค้นหาและแทนที่ซึ่งไม่สะดวก แต่ถ้าเป็นชื่อเมธอดจริง ๆ จะง่ายกว่าเพราะในโปรแกรมวิสชวลสตูดิโอมีเครื่องมือช่วยแปลงโค้ด (refactoring tool) ที่อำนวยความสะดวกให้การเปลี่ยนชื่อเมธอทำได้ง่าย สิ่งที่เราต้องทำคือเขียนนิยามเมธอดเพื่อขยาย ที่สามารถเรียกใช้ได้จากภายในคอนโทรลเลอร์ของเรา
บรรทัดที่ 5-9 เมธอดนี้มีพารามิเตอร์ซึ่งมีไทป์เป็นเจนเนอริกชื่อ Controller ซึ่งถูกนิยามไว้ในเบสคลาสของเฟรมเวิร์ก เมธอดนี้รับพารามิเตอร์เป็นแบบ Action<>
บรรทัดที่ 3 คือการอ้างถึงชื่อเมธอดโดยใช้สตริงก์ที่มีข้อเสียคือตอนเปลี่ยนชื่อเมธอดเราต้องพิมพ์ใหม่ทุกที่หรือใช้เครื่องมือค้นหาและแทนที่ซึ่งไม่สะดวก แต่ถ้าเป็นชื่อเมธอดจริง ๆ จะง่ายกว่าเพราะในโปรแกรมวิสชวลสตูดิโอมีเครื่องมือช่วยแปลงโค้ด (refactoring tool) ที่อำนวยความสะดวกให้การเปลี่ยนชื่อเมธอทำได้ง่าย สิ่งที่เราต้องทำคือเขียนนิยามเมธอดเพื่อขยาย ที่สามารถเรียกใช้ได้จากภายในคอนโทรลเลอร์ของเรา
บรรทัดที่ 5-9 เมธอดนี้มีพารามิเตอร์ซึ่งมีไทป์เป็นเจนเนอริกชื่อ Controller ซึ่งถูกนิยามไว้ในเบสคลาสของเฟรมเวิร์ก เมธอดนี้รับพารามิเตอร์เป็นแบบ Action<>
เมื่อมีนิพจน์ที่เป็นแลมบ์ดาสำหรับเมธอดที่ต้องการแล้ว เราก็สามารถตรวจสอบโครงสร้างข้อมูลของมันเพื่อหาชื่อของเมธอดได้โดยใช้โค้ดในรูป การทำงานของโค้ดขั้นแรกจะตรวจสอบว่ามีแลมบ์ดาที่ทำหน้าที่เป็นตัวแทนของการเรียกเมธอดอยู่จริงหรือไม่ ถ้าไม่มีให้ส่งเอ็กเซพชัน ถ้ามีให้เรียกเมธอด RedirectToAction อันที่รับสตริงก์หนึ่งตัว ซึ่งเป็นเมธอดที่มีชื่อปรากฏอยู่ภายในแลมบ์ดา จากนั้นเราจึงสามารถเรียกเมธอดต่อขยายเพื่อเปิดหน้าเว็บใหม่ จะเห็นว่าการใช้คอนโทรลเลอร์แบบนี้ทำให้เราสามารถใช้อินเทลลิเซนซ์และตัวเติมข้อความอัตโนมัติของโปรแกรมวิสชวลสตูดิโอรวมถึงเครื่องมืออำนวยความสะดวกในการแก้โค้ดอื่น ๆ ได้ นั่นหมายความว่าถ้าเราใช้คำสั่งเปลี่ยนชื่อ แลมบ์ดาจะถูกเปลี่ยนชื่อในทุกที่ ไม่ต้องใช้การค้นและแทนค่าสตริงก์ที่ไม่สะดวก หรืออย่างในกรณีที่เราใช้เฟรมเวิร์ก Fluent NHibernate เพื่อทำการแมปตารางในฐานข้อมูลให้เป็นออพเจ็กต์ของซีชาร์ป ซึ่งทำโดยเก็บค่าต่าง ๆ ไว้ในไฟล์ XML เราก็สามารถใช้เทคนิคเดียวกันนี้เพื่อให้ใช้อินเทลลิเซนซ์และตัวเติมข้อความอัตโนมัติของโปรแกรมวิสชวลสตูดิโอรวมถึงเครื่องมืออำนวยความสะดวกในการแก้โค้ดอื่น ๆ ได้เช่นกัน
รูปแสดงวิธีใช้แลมบ์ดาเพื่อการเข้าถึงพรอพเพอร์ตี เราใช้เจนเนอริก T เพื่อแทนไทป์ของคลาสที่มีพรอพเพอร์ตีนั้น ๆ นิยามอยู่ภายใน Func<T,V> คือฟังก์ชันที่รับไทป์ของคลาส เป็นพารามิเตอร์ตัวแรก และมี V เป็นค่าส่งกลับของพรอพเพอร์ตี การเขียนแบบนี้ช่วยให้เป็นแบบสตองก์ไทป์อย่างที่ควรจะเป็นในภาษาซีชาร์ปคล้าย ๆ โค้ดในตัวอย่างก่อนหน้านี้คือ ขั้นแรกเราตรวจสอบว่ามี MemberExpression อยู่จริงหรือไม่ โดย MemberExpression ทำหน้าที่เป็นตัวที่ให้เข้าถึงพรอพเพอร์ตีได้ เมื่อเรานำมันไปใช้กับ Fluent NHibernate ก็จะช่วยให้ไม่มีสตริงก์ที่มีลักษณะเป็นฮาร์ดโค้ด
ในเมื่อเราสามารถใช้นิพจน์เพื่อแยกส่วนแลมบ์ดาออกเพื่อตรวจสอบได้ เราก็สามารถสั่งให้มันทำงานได้ จากรูป แสดงวิธีทำให้ต้นไม้นิพจน์ทำงาน Expression<T> คือไทป์ที่มีเมธอด “Compile,” ซึ่งทำหน้าที่ตามที่ชื่อมันบอกคือคอมไพล์แลมบ์ดาที่ถูกกำหนดโดยนิพจน์
บรรทัดแรกเป็นนิยามนิพจน์ซึ่งทำหน้าที่แทนแลมบ์ดาซึ่งรับพารามิเตอร์เป็นเลขจำนวนเต็มตัวเดียว และมีค่าส่งกลับเป็นบูลีนซึ่งทำหน้าที่บอกให้รู้ว่าค่าของพารามิเตอร์เป็นเลขคู่หรือเลขคี่ จากนั้นเราคอมไพล์นิพจน์นั้นให้กลายเป็นเดลลิเกต สุดท้ายเราสามารถใช้งานเดลลิเกตนั้นได้อย่างเดลลิเกตทั่วไป
ปรกติเราจำเป็นต้องเขียนโค้ดเพื่อตรวจสอบความถูกต้องของค่าที่รับมาผ่านทางพารามิเตอร์ นี่เป็นงานน่าเบื่อแต่ก็จำเป็น เพราะไม่เช่นนั้นเมธอดของเราจะไม่ทนทาน และแอพลิเกชันจะทำงานไม่ได้อย่างที่ควรเป็น จากรูป แสดงตัวอย่างโค้ดง่าย ๆ เพื่อตรวจสอบว่าค่าของพารามิเตอร์สองตัวที่ส่งให้เมธอดคอนสทรักเตอร์ไม่ใช่นัล
เราสามารถใช้ประโยชน์จากต้นไม้นิพจน์เพื่อทำให้โค้ดตรวจสอบนี้เป็นมาตรฐานเดียวกัน และตัดส่วนกำหนดชื่อพารามิเตอร์ที่เป็นฮาร์ดโค้ดออกไป ซึ่งดีกว่า เพราะจะได้ประโยชน์จากอินเทลลิเซนซ์และตัวเติมข้อความอัตโนมัติของโปรแกรมวิสชวลสตูดิโอรวมทั้งเครื่องมืออำนวยความสะดวกในการแก้โค้ดอื่น ๆ ด้วย
ในรูป
บรรทัด 3-8 คือนิยามคลาส Validator ที่เป็นสแตติกคลาส ทำหน้าที่ใช้ประโยชน์จากต้นไม้นิพจน์เพื่อทำให้โค้ดตรวจสอบมีมาตรฐานเดียวกัน จากนั้นใส่นิยามเมธอดที่รับนิพจน์เป็นพารามิเตอร์
บรรทัด 3-8 คือนิยามคลาส Validator ที่เป็นสแตติกคลาส ทำหน้าที่ใช้ประโยชน์จากต้นไม้นิพจน์เพื่อทำให้โค้ดตรวจสอบมีมาตรฐานเดียวกัน จากนั้นใส่นิยามเมธอดที่รับนิพจน์เป็นพารามิเตอร์
การทำงานจะคล้ายโค้ดตัวอย่างก่อนหน้านี้ คือเราจะใช้นิพจน์นี้ทำหน้าที่แทนการเข้าถึงฟิลด์ (ในกรณีนี้เป็นพารามิเตอร์) เมื่อได้นิพจน์ที่ต้องการแล้วเราคอมไพล์มัน สั่งให้มันทำงาน และตรวจสอบให้แน่ใจว่าผลลัพธ์ (ค่าของพารามิเตอร์) ไม่ใช่นัล ในกรณีที่เป็นนัลเราจะให้เกิดเอ็กเซพชันที่แสดงชื่อของพารามิเตอร์จากต้นไม้นิพจน์ ไม่ใช่ชื่อที่ใส่ไว้แบบฮาร์ดโค้ด
บทความตอนนี้แสดงประโยชน์การใช้งานต้นไม้นิพจน์โดยแสดงวิธีประยุกต์ใช้ในลักษณะต่าง ๆ เช่นการนำต้นไม้นิพจน์มาใช้เพื่อสร้างหรือใช้งาน API ของเฟรมเวิร์ก และการใช้นิพจน์ต้นไม้เพื่อช่วยลดฮาร์ดโค้ด ที่ทำให้ได้ประโยชน์จากอินเทลลิเซนซ์และตัวเติมข้อความอัตโนมัติของโปรแกรมวิสชวลสตูดิโอ
โปรดติดตามบทความตอนต่อไปที่ยังมีเรื่องน่าสนใจเกี่ยวกับคุณสมบัติของภาษาซีชาร์ปที่เป็นข้อดีซึ่งไม่พบในภาษาอื่น