15.7 Code quality & maintainability
บทนี้รวบรวม debt ที่ไม่ได้ก่อให้เกิดความผิดพลาดทางเทคนิคโดยตรง แต่ทำให้โค้ดอ่านยาก maintain ยาก และเพิ่มความเสี่ยงเมื่อมีการแก้ไข
รายการทั้งหมด
LEG-14 · _bk files 131 ไฟล์ใน source
| ข้อมูล | รายละเอียด |
|---|---|
| Evidence | vtrc-web (57 ไฟล์) + vtrc-rc-backoffice (74 ไฟล์) — _bk, _copy, _removed, _pentest, _bak |
| ปัญหา | ไฟล์ backup ถูก commit ใน source — เพิ่ม noise ในการ review, ความเสี่ยงของการ import ไฟล์ผิด, ทำให้ codebase ดูใหญ่กว่าความเป็นจริง |
| Impact | การ maintainability ต่ำ การ onboard นักพัฒนาใหม่ใช้เวลานาน ความเสี่ยงในการ import ไฟล์ที่ตั้งใจปิด |
| Mitigation ระยะสั้น | ย้ายไป git history (ลบจาก working tree) เพิ่ม .gitignore + pre-commit hook |
| แนวทางระยะยาว | policy ที่ตรวจและปฏิเสธ commit ของไฟล์ backup |
LEG-21 · GraphQL operations ไฟล์ใหญ่
| ข้อมูล | รายละเอียด |
|---|---|
| Evidence | vtrc-web/src/graphql/queries.js (4,493 LOC) + vtrc-rc-backoffice/src/graphql/queries.js (4,108 LOC) + mutations.js (2,208 LOC) |
| ปัญหา | ไฟล์ monolith ที่รวม GraphQL operation ทั้งหมด — ทำให้ tree-shaking ไม่ได้, การ review ใช้เวลานาน, ความขัดแย้ง merge บ่อย |
| Impact | เวลา build ช้าลง, การพัฒนา feature ใหม่ต้องไปแก้ไฟล์เดียวกันกับคนอื่น |
| Mitigation ระยะสั้น | แยก operation ไป co-locate กับ feature ที่ใช้ |
| แนวทางระยะยาว | ใช้ Feature-Sliced Design — entities/<slice>/api/ |
LEG-22 · Role-based route duplication
| ข้อมูล | รายละเอียด |
|---|---|
| Evidence | vtrc-rc-backoffice/src/pages/ — LeaveStudies, LeaveStudiesAdmin, LeaveStudiesPayments, LeaveStudiesPaymentsAdmin, LeaveStudiesScholar, LeaveStudiesScholarAdmin |
| ปัญหา | หน้าที่คล้ายกัน 6 ชุดที่ต่างกันแค่สิทธิ์ — การแก้ bug ต้องแก้ 6 ที่ การ maintain ใช้เวลามาก |
| Impact | ความซ้ำซ้อนสูง, ความเสี่ยงว่าบาง role จะได้ behavior ที่ต่างจากที่ควร |
| Mitigation ระยะสั้น | รวมเป็นหน้าเดียวที่แสดง UI variant ตาม RBAC |
| แนวทางระยะยาว | ออกแบบ feature ที่ขับเคลื่อนด้วย RBAC ตั้งแต่ต้น |
LEG-23 · Resolver ไฟล์เดียว 3,716 บรรทัด
| ข้อมูล | รายละเอียด |
|---|---|
| Evidence | vtrc-api/api/src/resolvers/version.js — 3,716 LOC |
| ปัญหา | resolver ไฟล์เดียวที่ใหญ่มาก — มักสะสม logic ของ version history หรือหลาย domain |
| Impact | การ navigate ยาก การ review ใช้เวลานาน การแก้ส่วนหนึ่งมีผลข้างเคียงยากที่จะคาดการณ์ |
| Mitigation ระยะสั้น | แยก resolver ตาม bounded context |
| แนวทางระยะยาว | resolver แต่ละไฟล์ < 400 LOC (policy ใน CI) |
LEG-24 · console.log 77 ครั้งในไฟล์เดียว
| ข้อมูล | รายละเอียด |
|---|---|
| Evidence | vtrc-api/api/src/routes.js — grep -c console.log = 77 |
| ปัญหา | production code ใช้ console.log แทน structured logger — ไม่มี log level, ไม่มี structured output, ยากที่จะ filter |
| Impact | debug ยาก, log ไม่มีประโยชน์สำหรับ monitoring |
| Mitigation ระยะสั้น | เปลี่ยนเป็น structured logger (winston, pino) |
| แนวทางระยะยาว | policy ที่ห้าม console.log ใน production code |
LEG-25 · Typo ใน ENUM ที่ production
| ข้อมูล | รายละเอียด |
|---|---|
| Evidence | vtrc-api/api/src/models/core/leave/leave.js:59 + config.js:454,484 — PEDDING_CANCLE (PENDING_CANCEL), DRAF (DRAFT), TRANSECTION_ERROR (TRANSACTION_ERROR) |
| ปัญหา | typo ใน ENUM ที่ production ใช้ — การแก้ typo หมายถึง breaking change ของ schema ทำได้ยาก |
| Impact | ภาระ backward compatibility ถาวร นักพัฒนาใหม่ต้องจำ enum ที่สะกดผิด |
| Mitigation ระยะสั้น | ไม่มี — typo ไปแล้วใน schema สาธารณะ |
| แนวทางระยะยาว | map legacy string ไป canonical enum ที่ boundary ในการ rewrite |
LEG-26 · UI library ซ้อนกัน 4 ตัว
| ข้อมูล | รายละเอียด |
|---|---|
| Evidence | vtrc-rc-backoffice/package.json — primereact, @dnd-kit, react-sortable-hoc, array-move, PDF viewer 3 ตัว, icon set 3 ตัว, date library 2 ตัว |
| ปัญหา | ใช้ library หลายตัวที่ทำหน้าที่ซ้อนกัน — AntD + MUI + PrimeReact + styled-components ในแอปเดียว |
| Impact | bundle ใหญ่, cognitive load ของนักพัฒนา, ความไม่ consistent ของ UX |
| Mitigation ระยะสั้น | audit ว่า library ใดใช้จริง ลบอันที่ไม่ใช้ |
| แนวทางระยะยาว | policy: 1 design system, 1 icon set, 1 DnD lib, 1 date lib ต่อแอป |
LEG-30 · Error message ผสม TH/EN
| ข้อมูล | รายละเอียด |
|---|---|
| Evidence | vtrc-api/api/src/lib/responErrors.js ทั้งไฟล์ — error message ผสมภาษาไทยและอังกฤษ ('Session ถูกขัดจังหวะ หรือไม่ถูกต้อง') |
| ปัญหา | i18n ฝังใน error string ไม่ใช่ layer ที่แยกต่างหาก — เปลี่ยนภาษา error ต้องแก้ code |
| Impact | การ support หลายภาษาทำได้ยาก การ maintain error message กระจาย |
| Mitigation ระยะสั้น | แยก i18n ออกจาก error code |
| แนวทางระยะยาว | i18n ที่ presentation layer (@nuxtjs/i18n) error carry code, client localize |
รูปแบบที่ทำให้เกิด debt เหล่านี้
debt ในบทนี้เกิดจาก pattern ที่ซ้ำในหลายที่:
- "เก็บไว้ก่อน เดี๋ยวแก้ทีหลัง" — ไฟล์ backup, library ที่ลองแล้วไม่ใช้, code ที่ comment ไว้
- "อะไรก็ได้ที่ทำงาน" — typo ที่ ship ไป, console.log ที่ช่วย debug ครั้งนั้น
- "copy-paste ดีกว่า abstract" — หน้า 6 ชุด, queries 4,000 บรรทัดในไฟล์เดียว
- "เร็วกว่าที่จะคิด" — UI library ใหม่เพราะ component ที่ต้องการไม่มีในของเดิม
สรุป
| ID | รายการ | Severity | Effort ระยะสั้น |
|---|---|---|---|
| LEG-14 | _bk files 131 ไฟล์ | Med | 1-2 วัน |
| LEG-21 | GraphQL operations monolith | Med | 1-2 สัปดาห์ |
| LEG-22 | Route duplication | Med | 1 สัปดาห์ |
| LEG-23 | Resolver 3,716 LOC | Med | 1 สัปดาห์ |
| LEG-24 | console.log 77 ครั้ง | Med | 1 สัปดาห์ |
| LEG-25 | typo ใน ENUM | Med | (ไม่มี — map ตอน rewrite) |
| LEG-26 | UI library ซ้อนกัน | Med | 1 สัปดาห์ (audit) |
| LEG-30 | i18n ใน error string | Med | 2-3 วัน |
บทถัดไปจะไปยัง debt ด้าน build และ reproducibility ที่กระทบความสามารถในการ deploy และ debug ปัญหา