How to พัฒนา Frontend ให้ดียิ่งขึ้นด้วยหลักการ SOLID

การพัฒนา Frontend ไม่ใช่แค่สร้าง UI ให้ตรงกับ Design เท่านั้น แต่ยังมีโจทย์ที่สำคัญกว่านั้นคือ ทำอย่างไรให้เข้าใจการทำงานได้ง่าย, ปรับปรุงดูแลรักษา และขยายต่อได้ ในขณะที่ Application ยังคงถูกพัฒนาต่อไปเรื่อยๆ
เพราะฉะนั้น การออกแบบโครงสร้างที่จะต้องง่ายต่อการปรับปรุง และการนำไปใช้ซ้ำในงาน จึงเป็นสิ่งสำคัญสำหรับงานฝั่ง Frontend เพราะจะช่วยเพิ่มประสิทธิภาพในการทำงาน
เราอาจคุ้นชินกับการเขียน Vite/React ในรูปแบบ Functional Component แต่จริง ๆ แล้ว Vite/React เองก็สามารถเขียนในรูปแบบ Object Oriented Programming — OOP ได้เช่นเดียวกัน ในบทความนี้เราจะนำหลักการ SOLID ที่มักถูกใช้กับ OOP มาประยุกต์ใช้กับการพัฒนา Frontend กันบ้าง
ทำความเข้าใจกับ SOLID
เรามาทำความเข้าใจ SOLID ที่ไม่ใช่ของแข็ง แต่เป็นหลักการกันก่อน
SOLID เป็นหลักการออกแบบโปรแกรมเชิงวัตถุ (Object — Oriented Programming) 5 ข้อ มุ่งเน้นการออกแบบระบบให้มีความเข้าใจง่าย ยืดหยุ่น และสามารถปรับปรุง ดูแลรักษาได้ง่าย ถึงแม้ว่า SOLID จะถูกออกแบบมาเพื่อใช้พัฒนาการเขียนโปรแกรมเชิงวัตถุ แต่สามารถนำมาประยุกต์ใช้กับงานด้านอื่นๆ อีกด้วย เช่น Frontend
S — Single Responsibility principle (SRP):
‘A class should have one reason to change.’
Class ควรมีแค่เหตุผลเดียวที่จะทำให้มันเปลี่ยนแปลงได้ ตีความอีกนัยหนึ่งได้ว่า Class ควรมีความรับผิดชอบแค่สิ่งเดียว
สำหรับ Frontend แล้ว แต่ละ Component ที่เราสร้างควรทำหน้าที่เดียว ตัวอย่างเช่น
Button ทำหน้าที่รับ Interact จาก user โดยการกดปุ่ม การทำงานหลังจากนั้นไม่ควรที่จะยัดเข้ามาในปุ่มในก้อนเดียว

O — Open/Closed Principle (OCP):
‘Software entities should be open for extension but closed for modification.’
Class, Modules และฟังก์ชันที่ถูกสร้างขึ้น ควรออกแบบให้สามารถขยายได้ แต่ปิดไม่ให้มีการแก้ไข
อาจจะฟังดูขัดแย้งที่เราสามารถขยายฟังก์ชันการทำงานของ Class, Modules และ Function โดยที่ไม่ต้องแก้โค้ดที่อยู่
สามารถดูได้จากตัวอย่างนี้

จากโค้ดเดิม เป็นการสร้างปุ่มโดยใช้เงื่อนไขเพื่อแสดงผลการทำงาน โค้ดนี้จะมีปัญหาเมื่อเราต้องการเพิ่ม variant ของปุ่ม เช่น loading disabled ทำให้เรากลับไปแก้ไข Button ต้นแบบ ซึ่งทำให้ยากต่อการดูแล และปรับปรุงต่อในอนาคต
จึงสร้าง LinkButton ที่ดึง Button ต้นแบบมาปรับปรุงแทนการแก้ไขที่โค้ดหลัก
L — Liskov Substitution Principle (LSP):
‘Derived or child classes must be substitutable for their base or parent classes’
Class ย่อยที่ถูกสร้างขึ้นจาก Parent Class สามารถใช้อ้างถึง Parent Class
ใน Frontend Child component ที่สร้างขึ้นจาก Parent component ควรสามารถแทนที่ Parent component ได้โดยไม่ทำให้ behavior ของระบบผิดพลาด

จากโค้ดเดิม IconButton ไม่สามารถใช้แทนที่ Button ได้โดยตรง เพราะมี Props ที่แตกต่างกัน ทำให้ไม่สามารถเรียกใช้ onClick ได้
จึงแก้ไขโดยให้ IconButton สืบทอด Props จาก Button และใช้ Button มาเป็นต้นแบบ ทำให้ Component ทั้งสองสามารถใช้แทนที่กันได้
I — Interface Segregation Principle (ISP):
‘Do not force any client to implement an interface which is irrelevant to them’
กล่าวถึงการเลือกใช้ Interface ที่ไม่ควรบังคับให้ Client implement Interface โดยที่ไม่ได้ใช้ implement นั้น เป้าหมายหลักของข้อนี้คือ การหลีกเลี่ยงการเอา Interface ที่กว้างจนเกินไป มาใช้สำหรับ Class ที่เล็ก หรือSpecific มากๆ
ใน Frontend Props ควรที่จะชัดเจน ไม่โยนทุกอย่างเข้าไปจนรก เพื่อให้ง่ายต่อการนำไปใช้งาน และปรับปรุง Component นั้น

จากโค้ดเดิม TableUser รวมทุก Props ไว้ใน interface เดียว ทำให้ props เยอะและไม่ชัดเจน ทำให้ใช้งาน ดูแล และแก้ไขได้ยาก จึงได้แยก interface ตามหน้าที่ เช่น data, action และ UI แล้วนำมาประกอบเป็น TableProps วิธีนี้ช่วยให้ อ่านง่าย แก้ไขง่าย และ reuse ใช้ได้กับ Table รูปแบบอื่นๆ ได้ด้วย
D — Dependency Inversion principle (DIP):
‘High-level modules should not depend on low-level modules. Both should depend on abstractions.’
กล่าวถึง Module ระดับสูง ไม่ควรขึ้นกับ Module ระดับต่ำ แต่มันควรขึ้นอยู่กับ Abstract class หรือ Interface แทน
ตัวอย่างเช่น

จากโค้ดตัวอย่างด้านบน เราแยกการทำงานดึงข้อมูลจาก API ออกมาเป็น abstraction แยกจาก component เพื่อให้ UserProfile สามารถ reuse ดูแล และปรับปรุงได้ง่าย
ประโยชน์ของการนำ SOLID มาประยุกต์ใช้กับ Frontend
แม้ว่า SOLID จะถูกออกแบบมาสำหรับการเขียนโปรแกรมเชิงวัตถุ (Object Oriented Programming — OOP) ที่มักจะเห็นการประยุกต์ใช้แบบเห็นได้ชัดที่การทำงานฝั่ง Backend แต่เมื่อเรานำมาใช้กับ Frontend
- Maintainability: โค้ดที่สร้างขึ้นง่ายต่อการดูแล และปรับปรุง เมื่อโปรเจกต์ขยายใหญ่ขึ้น
- Testability: Component และฟังก์ชันการทำงานที่สร้างขึ้น ทำให้ง่ายต่อการเขียน unit test
- Reusability: Component และฟังก์ชันการทำงานที่สร้างขึ้น สามารถนำไปใช้ซ้ำได้ ซึ่งช่วยประหยัดเวลาการทำงาน
- Scalability: การเพิ่มฟีเจอร์ใหม่ทำได้โดยไม่กระทบโค้ดเดิม ทำให้โปรเจกต์ขยายได้ง่าย
จริง ๆ แล้ว SOLID ไม่ใช่กฎตายตัวที่ต้องทำตามทุกข้อ แต่เป็น Guideline ที่ช่วยให้เราเข้าใจโค้ดได้ง่ายขึ้น และปรับใช้ให้เหมาะกับแต่ละโปรเจกต์ได้
นอกจากนี้ยังมีอีกหลายแนวคิดและเทคนิค เช่น Clean Code, Design Patterns, Functional Programming หรือ Atomic Design ที่สามารถนำมาประยุกต์ใช้กับงานได้เช่นกัน
ขอบคุณที่ติดตามอ่านจนจบ แล้วพบกันใหม่ค่ะ 😊
อ้างอิง
Pieces, “SOLIDifying Your Front-end Code: Front-end Development Best Practices for Improved Readability and Maintainability,” DEV Community, Jun. 28, 2024. https://dev.to/get_pieces/solidifying-your-front-end-code-front-end-development-best-practices-for-improved-readability-and-maintainability-6hk
itsimiro, “Should we use SOLID principles in front-end development?,” Medium, Oct. 17, 2024. https://itsimiro.medium.com/should-we-use-solid-principles-in-front-end-development-2f54087cbf8b
K. Chris, “SOLID Design Principles in Software Development,” freeCodeCamp.org, Feb. 16, 2023. https://www.freecodecamp.org/news/solid-design-principles-in-software-development/
GeeksforGeeks, “SOLID Principles with Real Life Examples,” GeeksforGeeks, Oct. 12, 2019. https://www.geeksforgeeks.org/system-design/solid-principle-in-programming-understand-with-real-life-examples/
BorntoDev, “S.O.L.I.D Principles — BorntoDev เริ่มต้นเรียน เขียนโปรแกรม ขั้นเทพ !,” BorntoDev เริ่มต้นเรียน เขียนโปรแกรม ขั้นเทพ !, Jul. 24, 2023. https://www.borntodev.com/2023/07/24/s-o-l-i-d-principles/
Phayao Boonon, “S.O.L.I.D — 5 หลักการของ Object-Oriented Design,” Medium, Jul. 08, 2018. https://phayao.medium.com/s-o-l-i-d-5-%E0%B8%AB%E0%B8%A5%E0%B8%B1%E0%B8%81%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%82%E0%B8%AD%E0%B8%87-object-oriented-design-3c8a52821783