วิศวกรซอฟต์แวร์ถกเถียงเรื่องต้นทุนที่ซ่อนอยู่ของโค้ดที่ซับซ้อน: เมื่อการเขียนโปรแกรมที่ฉลาดกลายเป็นภาระ

ทีมชุมชน BigGo
วิศวกรซอฟต์แวร์ถกเถียงเรื่องต้นทุนที่ซ่อนอยู่ของโค้ดที่ซับซ้อน: เมื่อการเขียนโปรแกรมที่ฉลาดกลายเป็นภาระ

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

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

ปัญหาของโค้ดที่ฉลาด

นักพัฒนาที่มีประสบการณ์หลายคนกำลังตั้งคำถามว่าเทคนิคการเขียนโปรแกรมที่ซับซ้อนช่วยหรือเป็นอุปสรรคต่อประสิทธิภาพการทำงาน ชุมชนได้ระบุตัวการหลายอย่างที่เพิ่มภาระทางจิตใจ: การทำ abstraction มากเกินไป, การสืบทอดแบบลึกหลายชั้น, และ framework ที่ทำให้เกิดความคลุมเครือมากกว่าจะชี้แจง business logic

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

แหล่งที่มาทั่วไปของภาระงานทางปัญญาสูง

  • โครงสร้างการสืบทอดที่ลึก ( AdminController → UserController → GuestController )
  • ไมโครเซอร์วิสแบบตื้นเกินไป (ทีมหนึ่งมีไมโครเซอร์วิสมากกว่า 170 ตัวสำหรับนักพัฒนา 5 คน)
  • ชั้นนามธรรมที่มากเกินไปในสถาปัตยกรรมแบบ clean/hexagonal
  • การผูกมัดตรรกะทางธุรกิจเฉพาะเฟรมเวิร์ก
  • การใช้คุณสมบัติของภาษาโปรแกรมมิ่งมากเกินไปโดยไม่มีประโยชน์ที่ชัดเจน
การเปรียบเทียบทางภาพของสถานการณ์ภาระทางปัญญา: ผลกระทบของความซับซ้อนของงานเทียบกับลักษณะเฉพาะของนักพัฒนา
การเปรียบเทียบทางภาพของสถานการณ์ภาระทางปัญญา: ผลกระทบของความซับซ้อนของงานเทียบกับลักษณะเฉพาะของนักพัฒนา

ปัญหาของ Business Logic

แง่มุมที่น่าสนใจของการถกเถียงนี้เน้นไปที่การพัฒนาซอฟต์แวร์ทางธุรกิจ วิศวกรหลายคนสังเกตว่าความต้องการทางธุรกิจมีความยุ่งเหยิงโดยธรรมชาติและเปลี่ยนแปลงอยู่ตลอดเวลา ทำให้เกิดสิ่งที่นักพัฒนาคนหนึ่งเรียกว่า pile-of-if-statements architecture แม้ว่าแนวทางนี้อาจดูไม่สวยงาม แต่หลายคนโต้แย้งว่าจริงๆ แล้วมันดูแลรักษาได้ง่ายกว่า abstraction ที่ซับซ้อนซึ่งจะพังเมื่อความต้องการเปลี่ยนแปลงอย่างหลีกเลี่ยงไม่ได้

คุณไม่สามารถสร้าง abstraction ที่ระมัดระวังและปราศจากบั๊กในสภาพแวดล้อมองค์กรได้ เพราะเจ้าของ business logic ไม่ได้ปฏิบัติต่อ business logic ด้วยความระมัดระวังเพียงพอ

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

กับดัก Framework

จุดอภิปรายสำคัญอีกประเด็นหนึ่งเกี่ยวข้องกับความสัมพันธ์ระหว่างนักพัฒนาและ framework แม้ว่า framework จะสัญญาว่าจะลดความซับซ้อน แต่มักจะสร้าง cognitive overhead ของตัวเอง ทีมงานอาจจับคู่กับวิธีการทำงานของ framework อย่างแน่นหนาจนต่อสู้เมื่อความต้องการเปลี่ยนแปลงหรือเมื่อ framework เองกลายเป็นข้อจำกัด

ชุมชนแนะนำให้แยก business logic ออกจากโค้ดที่เฉพาะเจาะจงกับ framework เพื่อให้ทีมได้ประโยชน์จาก framework โดยไม่กลายเป็นนักโทษของการตัดสินใจทางสถาปัตยกรรม

บุคลิกนักพัฒนาของ Microsoft

มุมมองทางประวัติศาสตร์ที่น่าสนใจเกิดขึ้นจากอดีตพนักงาน Microsoft ที่แบ่งปันระบบการจำแนกนักพัฒนาเก่าของบริษัท พวกเขาอธิบายถึงสามประเภท: Mort ผู้ใช้งานจริงที่เน้นผลลัพธ์ทางธุรกิจ, Elvis ผู้ขับเคลื่อนนวัตกรรมที่แสวงหาการมองเห็นผ่านเทคโนโลยีใหม่, และ Einstein ผู้สมบูรณ์แบบที่ให้ความสำคัญกับความสง่างามทางเทคนิคมากกว่าข้อกังวลเชิงปฏิบัติ

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

บุคลิกภาพนักพัฒนาของ Microsoft (ในอดีต)

  • Mort: วิศวกรที่มุ่งเน้นการปฏิบัติจริง เน้นผลลัพธ์ทางธุรกิจและการส่งมอบงานอย่างรวดเร็ว
  • Elvis: วิศวกรที่ขับเคลื่อนด้วยนวัตกรรม แสวงหาการมองเห็นผ่านเทคโนโลยีใหม่ๆ
  • Einstein: วิศวกรที่เป็นนักสมบูรณ์นิยม ให้ความสำคัญกับความสง่างามทางเทคนิคและความถูกต้องของอัลกอริทึม

การหาสมดุล

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

การถกเถียงยังเน้นความสำคัญของความมั่นคงของทีมและการถ่ายทอดความรู้ ปัญหาความซับซ้อนที่เลวร้ายที่สุดหลายอย่างเกิดขึ้นเมื่อระบบเปลี่ยนมือบ่อยครั้ง ทำให้ผู้ดูแลคนใหม่ต้องวิศวกรรมย้อนกลับเพื่อหากระบวนการคิดของนักพัฒนาเดิม

กลยุทธ์สำหรับการลดภาระทางปัญญา

  • ใช้ตัวแปรกลางที่มีชื่อบอกความหมายแทนการใช้เงื่อนไขที่ซับซ้อน
  • เลือกใช้การประกอบแทนการสืบทอด
  • แยกตรรกะทางธุรกิจออกจากโค้ดของเฟรมเวิร์ก
  • มุ่งเน้นที่ "โมดูลเชิงลึก" ที่มีอินเทอร์เฟซที่เรียบง่ายแต่มีฟังก์ชันการทำงานภายในที่ซับซ้อน
  • จัดทำเอกสารทั้ง "อะไร" และ "ทำไม" ของส่วนโค้ดที่ซับซ้อน
ภาพประกอบแสดงความแตกต่างของภาระทางปัญญาระหว่างนักพัฒนาที่มีประสบการณ์และผู้เข้ามาใหม่ เน้นย้ำถึงความสำคัญของการเข้าใจแบบจำลองทางความคิด
ภาพประกอบแสดงความแตกต่างของภาระทางปัญญาระหว่างนักพัฒนาที่มีประสบการณ์และผู้เข้ามาใหม่ เน้นย้ำถึงความสำคัญของการเข้าใจแบบจำลองทางความคิด

บทสรุป

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

อ้างอิง: Cognitive Load is what matters