ขับเคลื่อนด้วยความต้องการ (Needs driven)
— คุณระบุเป้าหมายไม่ได้เหรอว่าฟีเจอร์ใหม่นี้จะแก้ปัญหาอะไร? หรือปัญหาคือตัวโจทย์เองก็ยังไม่ได้ตั้งมาให้ชัด? ประเด็นคือ Methodology นี้ช่วยดึงเอานิยามของงานและเป้าหมายที่เป็นปัญหาออกมาให้เห็นชัดขึ้น
— โปรเจกต์ไม่ได้อยู่นิ่งๆ - Requirement และฟังก์ชันการทำงานเปลี่ยนตลอดเวลา นานวันเข้า โค้ดก็เละตุ้มเป๊ะ เพราะตอนเริ่ม โปรเจกต์ถูกออกแบบมาแค่ตามความต้องการแรกเริ่ม และหน้าที่ของสถาปัตยกรรมที่ดีคือต้องพร้อมรับมือกับเงื่อนไขการพัฒนาที่เปลี่ยนแปลงไป
ทำไม? (Why?)
เพื่อที่จะเลือกชื่อที่ชัดเจนให้กับ Entity และเข้าใจส่วนประกอบของมัน คุณต้องเข้าใจให้ชัดก่อนว่าโจทย์ข้อไหนจะถูกแก้ด้วยโค้ดกองนี้
@sergeysova: ระหว่างการพัฒนา เราพยายามตั้งชื่อให้แต่ละ Entity หรือ Function เพื่อสะท้อนความตั้งใจและความหมายของโค้ดที่กำลังทำงานอยู่ให้ชัดเจน
เพราะถ้าไม่เข้าใจโจทย์ ก็เป็นไปไม่ได้เลยที่จะเขียน Test ที่ถูกต้องและครอบคลุมเคสสำคัญๆ, ใส่ Error handling ที่ช่วยผู้ใช้ในจุดที่ถูกต้อง, หรือแม้แต่เรื่องพื้นฐานอย่างการไม่ขัดจังหวะ Flow ของผู้ใช้เพียงเพราะ Error เล็กๆ น้อยๆ ที่แก้ได้
เรากำลังพูดถึงโจทย์อะไร?
Frontend พัฒนาแอปพลิเคชันและอินเตอร์เฟสสำหรับผู้ใช้ปลายทาง (End users) ดังนั้นเราจึงแก้โจทย์ของผู้บริโภคเหล่านี้
เมื่อคนคนนึงมาหาเรา เขาต้องการแก้ความเจ็บปวดบางอย่าง หรือตอบสนองความต้องการบางอย่าง
หน้าที่ของ Managers และ Analysts คือการระบุความต้องการนี้ออกมา และให้นักพัฒนา Implement โดยคำนึงถึงธรรมชาติของการทำเว็บ (เน็ตหลุด, Backend error, พิมพ์ผิด, จิ้มพลาด)
เป้าหมายนี้แหละ ที่ผู้ใช้มาหาเรา คือโจทย์ของนักพัฒนา
ปัญหาเล็กๆ หนึ่งข้อที่ถูกแก้ คือหนึ่ง Feature ในระเบียบวิธี Feature-Sliced Design — คุณต้องหั่น (Cut) ขอบเขตงานทั้งหมดของโปรเจกต์ออกเป็นเป้าหมายเล็กๆ
มันส่งผลกับการพัฒนายังไง?
การแตกงาน (Task decomposition)
เมื่อนักพัฒนาเริ่ม Implement งาน เพื่อให้เข้าใจและดูแลโค้ดได้ง่าย เขาจะ หั่นมันออกเป็นระยะๆ ในหัว:
- ก่อนอื่น แบ่งเป็น Top-level entities และ Implement พวกมัน
- จากนั้น Entities พวกนี้ ก็ถูกแบ่งย่อยลงไปอีก
- และทำแบบนี้ไปเรื่อยๆ
ในกระบวนการแบ่งเป็น Entities นักพัฒนาจะถูกบังคับให้ตั้งชื่อที่สะท้อนไอเดียของเขา และช่วยให้คนอ่านโค้ดเข้าใจว่าโค้ดนี้แก้โจทย์อะไร ในขณะเดียวกัน เราก็ไม่ลืมว่าเรากำลังพยายามช่วยลดความเจ็บปวดหรือตอบสนองความต้องการของผู้ใช้
เข้าใจแก่นของงาน (Understanding the essence of the task)
แต่การจะตั้งชื่อที่ชัดเจนให้ Entity ได้ นักพัฒนาต้องรู้มากพอเกี่ยวกับจุดประสงค์ของมัน
- เขาจะใช้ Entity นี้ยังไง
- มัน Implement ส่วนไหนของโจทย์ผู้ใช้, เอาไปใช้ที่อื่นได้อีกมั้ย
- มันเอาไปใช้กับโจทย์อื่นได้รึเปล่า
- และอื่นๆ
สรุปได้ไม่ยาก: ในขณะที่นักพัฒนากำลังไตร่ตรองชื่อของ Entities ภายใต้กรอบของ Methodology เขาจะสามารถเจอโจทย์ที่ตั้งมาไม่ชัดเจนได้ตั้งแต่ก่อนเริ่มเขียนโค้ดด้วยซ้ำ
จะตั้งชื่อ Entity ยังไงถ้ายังไม่เข้าใจดีพอว่ามันแก้โจทย์อะไรได้บ้าง, แล้วจะแบ่งงานเป็น Entities ได้ยังไงถ้ายังไม่เข้าใจมันดีพอ?
จะกำหนดยังไงดี? (How to formulate it?)
เพื่อกำหนดโจทย์ที่ถูกแก้ด้วย Features คุณต้องเข้าใจตัวโจทย์เองก่อน และนี่เป็นความรับผิดชอบของ Project Manager และ Analysts
Methodology ทำได้แค่บอกนักพัฒนาว่าโจทย์ไหนที่ Product Manager ควรให้ความสำคัญ
@sergeysova: Frontend ทั้งหมดโดยหลักการคือการแสดงผลข้อมูล, Component ใดๆ ก็ตาม อย่างแรกสุดคือแสดงผล, ดังนั้นโจทย์แค่ "ให้แสดงอะไรบางอย่างให้ผู้ใช้ดู" จึงไม่มีคุณค่าในทางปฏิบัติ
แม้จะไม่นับรวมธรรมชาติของ Frontend ก็ยังถามได้ว่า "ทำไมฉันต้องแสดงให้คุณดู", ถามไปเรื่อยๆ จนกว่าจะเจอความเจ็บปวดหรือความต้องการของผู้บริโภค
ทันทีที่เราเข้าถึงความต้องการพื้นฐานหรือจุดเจ็บปวด (Pain points) เราก็สามารถย้อนกลับมาดูได้ว่า Product หรือ Service ของคุณจะช่วยผู้ใช้ให้บรรลุเป้าหมายได้อย่างไร
งานใหม่ๆ ใน Tracker ของคุณมุ่งเป้าไปที่การแก้ปัญหาทางธุรกิจ และธุรกิจก็พยายามแก้ปัญหาของผู้ใช้ในขณะเดียวกันก็หาเงินจากมันด้วย นั่นหมายความว่าแต่ละงานมีเป้าหมายบางอย่าง แม้ว่าจะไม่ได้เขียนไว้ในคำอธิบายก็ตาม
นักพัฒนาต้องเข้าใจอย่างชัดเจนว่างานนี้มีเป้าหมายอะไร, แต่ไม่ใช่ทุกบริษัทจะสามารถสร้างกระบวนการที่สมบูรณ์แบบได้ (ถึงแม้นั่นจะเป็นอีกเรื่องนึง) แต่อย่างน้อย นักพัฒนาก็สามารถ "Ping" หา Manager ที่เกี่ยวข้องเพื่อหาคำตอบและทำงานในส่วนของตัวเองให้มีประสิทธิภาพได้
แล้วประโยชน์คืออะไร? (And what is the benefit?)
ทีนี้มาดูกระบวนการทั้งหมดตั้งแต่ต้นจนจบกัน
1. เข้าใจโจทย์ของผู้ใช้
เมื่อนักพัฒนาเข้าใจ Pain point และวิธีที่ธุรกิจจะตอบโจทย์นั้น เขาสามารถเสนอ Solution ที่ธุรกิจอาจนึกไม่ถึงเนื่องจากข้อจำกัดทางเทคนิคของการทำเว็บ
แต่แน่นอน ทั้งหมดนี้จะเวิร์คก็ต่อเมื่อนักพัฒนาไม่ได้เมินเฉยต่อสิ่งที่กำลังทำและเหตุผลที่ทำ ไม่งั้น จะมี Methodology และแนวทางต่างๆ ไปทำไม?
2. การจัดโครงสร้างและลำดับ
ด้วยความเข้าใจในโจทย์ โครงสร้างที่ชัดเจนจะเกิดขึ้นทั้งในหัว ใน Task งาน และในโค้ด
3. เข้าใจ Feature และส่วนประกอบของมัน
หนึ่ง Feature คือหนึ่งฟังก์ชันที่มีประโยชน์สำหรับผู้ใช้
- เมื่อหลาย Features ถูก Implement ใน Feature เดียว นี่คือ การละเมิดเส้นแบ่ง (Violation of borders)
- Feature สามารถแบ่งไม่ได้และโตขึ้นเรื่อยๆ - อันนี้ไม่แย่
- ที่แย่ - คือเมื่อ Feature ไม่ตอบคำถามที่ว่า "คุณค่าทางธุรกิจสำหรับผู้ใช้คืออะไร?"
- จะไม่มี Feature ที่ชื่อ "map-office" (แผนที่-ออฟฟิศ)
- แต่
booking-meeting-on-the-map(จองห้องประชุมบนแผนที่),search-for-an-employee(ค้นหาพนักงาน),change-of-workplace(เปลี่ยนที่นั่งทำงาน) - อันนี้ได้
- แต่
@sergeysova: ประเด็นคือ Feature ควรมีแค่โค้ดที่ Implement ตัวฟังก์ชันการทำงานนั้นๆ, โดยไม่มีรายละเอียดที่ไม่จำเป็นและ Internal solutions (ในอุดมคตินะ)*
เปิดโค้ด Feature มา แล้วเห็นเฉพาะสิ่งที่เกี่ยวกับโจทย์ - ไม่มีอะไรเกินกว่านั้น
4. กำไร (Profit)
ธุรกิจน้อยมากที่จะกลับลำ 180 องศา ซึ่งหมายความว่า ภาพสะท้อนของโจทย์ธุรกิจที่อยู่ในโค้ด Frontend คือกำไรที่สำคัญมาก
แล้วคุณจะไม่ต้องมานั่งอธิบายให้สมาชิกทีมใหม่ฟังว่าโค้ดนั้นโค้ดนี้ทำอะไร และโดยทั่วไปทำไมถึงเพิ่มมันเข้ามา - ทุกอย่างจะถูกอธิบายผ่านโจทย์ธุรกิจที่สะท้อนออกมาในโค้ดอยู่แล้ว
สิ่งที่เรียกว่า "Business Language" ใน Domain Driven Development
กลับสู่โลกความจริง (Back to reality)
ถ้า Process ธุรกิจเป็นที่เข้าใจและมีการตั้งชื่อที่ดีในขั้นตอน Design - มันก็ไม่ยากเท่าไหร่ที่จะส่งต่อความเข้าใจและ Logic นี้ไปสู่โค้ด
อย่างไรก็ตาม ในทางปฏิบัติ งานและฟังก์ชันมักจะถูกพัฒนาแบบ "โคตร" Iterative (ทำไปแก้ไป) และ (หรือ) ไม่มีเวลามาคิดเรื่อง Design ให้ละเอียด
ผลก็คือ Feature ที่สมเหตุสมผลในวันนี้ ถ้าขยาย Feature นี้ในอีกหนึ่งเดือน อาจจะต้องรื้อโปรเจกต์ใหม่เลยก็ได้
[จากการอภิปราย]: นักพัฒนาพยายามคิดล่วงหน้า 2-3 step โดยคำนึงถึงความต้องการในอนาคต แต่ตรงนี้เขาก็ต้องพึ่งประสบการณ์ของตัวเอง
วิศวกรที่เก๋ามักจะมองข้ามช็อตไป 10 step ทันที และเข้าใจว่า Feature ไหนควรแบ่ง หรือควรรวมกับอันไหน
แต่บางครั้งก็เจองานที่ต้องงัดประสบการณ์มาสู้ และไม่รู้จะไปหาความเข้าใจมาจากไหนว่าจะ Decompose (แตกงาน) ยังไงให้ฉลาด และส่งผลเสียในอนาคตน้อยที่สุด
บทบาทของ Methodology
Methodology ช่วยแก้ปัญหาของนักพัฒนา เพื่อให้ง่ายต่อการแก้ปัญหาของผู้ใช้
ไม่มี Solution ไหนที่แก้ปัญหาของนักพัฒนาเพื่อนักพัฒนาเท่านั้น
แต่เพื่อให้นักพัฒนาแก้โจทย์ของเขาได้ คุณต้องเข้าใจโจทย์ของผู้ใช้ - ถ้ากลับกัน (เข้าใจแต่โจทย์ตัวเอง) มันจะไม่เวิร์ค
ความต้องการของ Methodology
เริ่มชัดเจนแล้วว่าเราต้องระบุความต้องการอย่างน้อยสองข้อสำหรับ Feature-Sliced Design:
-
Methodology ควรอบอกว่า จะสร้าง Features, Processes และ Entities อย่างไร
- ซึ่งหมายความว่ามันควรจะอธิบายอย่างชัดเจนว่า จะแบ่งโค้ดระหว่างพวกมันยังไง และนั่นหมายความว่าการตั้งชื่อ Entities เหล่านี้ควรถูกกำหนดไว้ใน Specification ด้วย
-
Methodology ควรช่วยให้สถาปัตยกรรม ปรับตัวตาม Requirement ของโปรเจกต์ที่เปลี่ยนแปลงได้ง่าย
ดูเพิ่มเติม
- (Post) Stimulation for a clear formulation of tasks (+ discussion)
บทความนี้ คือการดัดแปลงจากการอภิปรายนี้, คุณสามารถอ่านเวอร์ชันเต็มแบบไม่ตัดทอนได้ที่ลิงก์
- (Discussion) How to break the functionality and what it is
- (Article) "How to better organize your applications"