จากหนังสือ Beyond Legacy Code นั้น
ในบทที่ 9 อธิบายเกี่ยวกับ CLEAN code
ซึ่งมีความน่าสนใจมากมาย
ดังนั้นจึงนำมาสรุปไว้นิดหน่อยสิ
ที่มาของ CLEAN code
มาจากหนังสือ Clean Code: A Handbook of Agile Software Craftsmanship
ของคุณ Robert C. Martin (Uncle Bob)
เป็นแนวปฏิบัติที่มีเป้าหมายให้ developer เขียน code ที่มีคุณภาพที่ดีขึ้น
ทั้งเข้าใจง่าย
ทั้งทดสอบได้ง่าย
ทั้งแก้ไขง่าย
ทั้งดูแลรักษาง่าย
โดยในเรื่องคุณภาพของ code นั้นมันอาจจะเป็นสิ่งที่เล็กน้อย
แต่ว่าความเล็กน้อยนี้ มันสร้างความแตกต่างได้อย่างมหาศาล !!
ยิ่งในโลกของ Object-Oriented ด้วยแล้วนั้นยิ่งสำคัญมาก ๆ เช่น
- แต่ละ object ควรมีหน้าที่การทำงานชัดเจน
- แต่ละ object ควรมีพฤติกรรมการทำงานที่ชัดเจน
- แต่ละ object ควรมีการซ่อนการทำงาน หรือการ implementation ไว้ภายใน
- และอื่น ๆ อีกมากมาย
ซึ่งมันคือที่มาของ CLEAN code
ประกอบไปด้วย
- C => Cohesive
- L => Loosely Coupled
- E => Encapsulated
- A => Assertive
- N => Non-Redundant
ดังนั้นเรามาดูรายละเอียดของแต่ละตัวว่าเป็นอย่างไรกันบ้าง ?
1. Cohesive
เป็นสิ่งแรกของ code ที่ดี และ มีคุณภาพที่ดี นั่นคือ
แต่ละส่วนการทำงานควรทำงานเพียงอย่างเดียว (Single Responsibility)
ทั้ง class และ method นะ
ทำให้ code ที่ได้ออกมานั้น เข้าใจง่าย และ ทำงานด้วยง่าย
ที่สำคัญมันช่วยทำให้เราสร้างระบบง่ายอีกด้วย
แต่สิ่งที่น่าแปลกใจ คือ developer มักจะทำในทางตรงข้าม
ซึ่งเรามักจะได้ยินคำว่า God Class/Object
โดยที่ God class นั้นไม่ใช่ว่ามีการทำงานทุกสิ่งอย่างอยู่ในนั้นนะ
แต่แท้จริงแล้วมันคือ class ที่ยากต่อการแก้ไขต่างหากล่ะ !!!
ดังนั้นมาเขียน code เพื่อให้แต่ละส่วนทำงานเพียงอย่างเดียวเถอะนะ
สิ่งแรกที่เราทำได้ง่าย คือ เรื่องการตั้งชื่อ
ถ้าชื่อมันไม่สื่อสารถึงหน้าที่การทำงาน
แสดงว่า เรายังตั้งชื่อไม่ดี
หรือเป็นว่าหน้าที่การทำงานมันเยอะเกินไป !!
ต้องปรับปรุงให้ดีขึ้นนะครับ
คำถาม
สำหรับระบบที่ซับซ้อนขึ้นล่ะ เราจะยังสร้าง code ที่ยังคงคุณสมบัติ Cohesive อยู่ได้ไหม ?
คำตอบ
ได้สิ โดยให้ใช้การ composition เอานะ
2. Loosely Coupled
ต่อมาว่าด้วยเรื่องของความสัมพันธ์ของ code แต่ละส่วนบ้าง (Relationship)
โดยที่แต่ละส่วนควรแยกกันชัดเจน ไม่ผูกมัดกันแน่น
ซึ่ง code ที่มีความสัมพันธ์แบบนี้จะเป็นแบบ indirection
ส่งผลทำให้ code มันง่ายต่อการ
- แยกกันทำงาน
- ทดสอบการทำงาน
- ตรวจสอบการทำงาน
- การ reuse
- การ extend หรือ ขยาย
ในส่วนของ indirection นั้นเราสามารถใช้งาน
Abstract class และ Interface มาช่วยได้นะ
และเราสามารถ inject สิ่งที่เราต้องการเข้าไปได้ง่าย
นั่นหมายความว่า
ให้เราสนใจในส่วนของ abstraction มากกว่า implementation จริง ๆ นะ
แต่ว่า code ไม่จำเป็นต้องมีความสัมพันธ์แบบ loose coupling เสมอไปนะ
อาจจะเป็น tight coupling ก็ได้ ขึ้นอยู่กับริบทของระบบงาน
3. Encapsulated
คือซ่อนการ implementation ของการทำงานหนึ่ง ๆ ไว้ซะ
เป็นประโยชน์จากภาษา Object-Oriented เลยนะ
โดย encapsulation มันไม่ได้หมายถึง
การที่ใส่ private ไว้หน้า method และ property เท่านั้น
แต่เรายังทำการซ่อน interface หรืออะไรก็ตามที่เราต้องการ
จากการ implementation หรือวิธีการสร้างสิ่งที่เราต้องการ
การ encapsulation ที่ดี
มันคือการสร้าง และ ออกแบบจากภายนอกสู่ภายใน หรือ (Outside-in)
นั่นคือ เราสนใจ What คือสิ่งที่เราต้องการ
มากกว่า How คือวิธีการสร้างสิ่งที่ต้องการ
เราจะสนใจว่าแต่ละ service ที่กำลังจะสร้างนั้น
ผู้ใช้งานจริง ๆ ต้องการอะไรบ้าง
ผู้ใช้งานจริง ๆ มีพฤติกรรมการใช้งานอย่างไร
มันจะทำให้เราเห็นในภาพรวมของทั้งระบบ
จากนั้นเราจึงลงมือสร้างในแต่ละส่วนต่อไป
4. Assertive
เป็นการจัดการว่าแต่ละส่วนมันคือ หน้าที่ของมันจริง ๆ นะ
ไม่ใช่ว่าไปทำงานในหน้าที่ของส่วนอื่นซะอย่างนั้น
เป็นแนวปฏิบัติที่พูดถึงกันน้อยมาก ๆ
แต่มันช่วยเราตัดสินใจว่า
เราควรใส่พฤติกรรมการทำงานหนึ่งใน object ใด
และทำให้แต่ละ object มีหน้าที่การทำงานที่ถูกต้องและเหมาะสม
ตัวอย่างเช่น
ถ้าเรามี class Document ทำหน้าที่เป็นตัวแทนของเอกสาร
ทำการจัดรูปแบบของเอกสารแต่ละชนิด
คำถาม
ถ้าเราต้องการพิมพ์เอกสารนี้ออกมาล่ะ จะทำอย่างไร ?
คำตอบ
ง่ายสุด ๆ คือ ก็เพิ่ม method print() ใน class Document ไปเลยสิครับ !!!
หรือบางคนบอกว่า งั้นก็สร้าง class Printer มาเลยสิ
เอายังไงดีล่ะ ?
ถ้าถาม developer เลยเขาก็จะบอกว่า
class Printer สิ ซึ่งมีหน้าที่ควบคุมการพิมพ์เอกสาร
แต่เดี๋ยวก่อนนะ ลองคิดดูหน่อยสิว่า
ใครรู้ว่าเอกสารจะถูกพิมพ์ ?
Document หรือ Printer ที่รู้ ?
Document ใช่หรือไม่ นั่นคือสถานะของการพิมพ์ของแต่ละเอกสาร
แต่ไม่จำเป็นต้องรู้ว่า Printer ทำการพิมพ์อย่างไร
รู้เพียงว่าถ้าจะพิมพ์ออกมาให้ไปเรียกใช้ หรือ ส่งงานไปยัง Printer แทนก็พอ
ดังนั้นแต่ละ object นั้น
ควรที่จะจัดการสถานะของตัวมันเอง
ไม่ควรให้ object อื่น ๆ มาจัดการนะ
ไม่เช่นนั้นนรกแตกแน่นอน …
หรือไม่เช่นนั้นจะเกิดปัญหา หรือ Code smell ที่เรียกว่า Feature Envy ขึ้นมา
5. Non-Redundant
เรื่องสุดท้ายมันก็สำคัญมาก ๆ นั่นคือ อย่าทำซ้ำ
ท่องไว้เลยสัก 3 รอบ ว่า
อย่าทำซ้ำ
อย่าทำซ้ำ
อย่าทำซ้ำ
เราพบว่าถ้ามี code ที่มันซ้ำ ๆ อยู่เป็นจำนวนมาก
ส่งผลให้ค่าใช้จ่ายในการแก้ไข และ ดูแลรักษาสูงมากมาย
เนื่องจากแทนที่จะแก้ไขเพียงที่เดียว ดันต้องไปแก้ไขหลายที่ !!
มันคือปีศาจร้ายของการพัฒนา software กันเลยทีเดียว
ที่น่าแปลกใจคือ developer ส่วนใหญ่ชอบทำซ้ำ !!
ดังนั้น
อะไรที่ทำซ้ำให้สร้างระบบทำงานแบบอัตโนมัติขึ้นมาซะ
อะไรที่ทำซ้ำ ให้ลด ละ เลิก ซะ
แนวปฏิบัติที่ไปในทิศทางเดียวกัน คือ
- DRY (Don’t Repeat Yourself)
- Once And Only Once
ปล. เรามักจะพบว่า การหาส่วนที่มันซ้ำกันนั้นยากมาก !!
สุดท้ายแล้ว
“Good code is CLEAN code”
และการเพิ่มคุณภาพของ code วันนี้
เพื่อความเร็วในการพัฒนาสำหรับวันพรุ่งนี้นะ
วันนี้คุณ CLEAN code กันแล้วหรือยังครับ ?