แนวทางการตั้งชื่อฐานข้อมูลสำหรับแผงแอดมินให้อ่านง่าย
ใช้แนวทางตั้งชื่อฐานข้อมูลสำหรับแผงแอดมินเพื่อให้หน้าจอที่สร้างอัตโนมัติอ่านง่าย: กฎตั้งชื่อตารางและฟิลด์ ชุด enum ความสัมพันธ์ และเช็คลิสต์ด่วน

ทำไมชื่อนั้นตัดสินว่าแผงแอดมินดูชัดเจนหรือละเอียด\n\nแผงแอดมินส่วนใหญ่สร้างจากโมเดลข้อมูลของคุณ ชื่อของตารางและฟิลด์จะกลายเป็นเมนู ชื่อเพจ หัวคอลัมน์ ป้ายฟิลเตอร์ และแม้แต่คำที่ผู้คนพิมพ์ค้นหา\n\nเมื่อชื่อชัดเจน ผู้ดูแลสามารถสแกนรายการแล้วเข้าใจได้ในไม่กี่วินาที แต่ถ้าชื่อไม่ชัดเจน พวกเขาจะหยุด เดา เปิดดูระเบียน กลับไป แล้วลองใหม่ ความลังเลนั้นสะสมเป็นคำถามเช่น “ฉันจะหาลูกค้าที่ถูกต้องได้อย่างไร?” และเอกสารฝึกอบรมที่ไม่มีใครอยากอ่าน\n\nนักพัฒนามักตั้งชื่อให้เหมาะกับการพัฒนาและดีบัก ส่วนผู้ปฏิบัติงานตั้งชื่อเพื่อให้ทำงานได้ง่าย นักพัฒนาอาจโอเคกับ acct, addr1, หรือ stat เพราะจดจำความหมายได้ แต่ผู้ปฏิบัติงานต้องเห็น “Account”, “Address line 1”, และ “Status” โดยไม่ต้องถอดรหัส\n\nในหน้าจอแอดมิน “อ่านง่าย” มักหมายถึง:\n\n- คุณสามารถสแกนตารางแล้วเข้าใจแต่ละคอลัมน์โดยไม่ต้องเปิดแถว\n- คุณสามารถค้นหาและกรองโดยใช้คำเดียวกับคำที่ใช้ในงานประจำวัน\n- คุณสามารถเรียงและเปรียบเทียบค่าโดยไม่มีความประหลาดใจ (เช่น วันที่เป็นวันที่จริง และสถานะมีความสอดคล้อง)\n\nถ้าคุณใช้แพลตฟอร์มที่สร้างหน้าจอจากโมเดล (เช่น Data Designer ของ AppMaster และมุมมองแบบแอดมิน) การตั้งชื่อกลายเป็นส่วนหนึ่งของการออกแบบ UI ชื่อที่ดีจะให้หน้าจอเริ่มต้นที่สะอาดตั้งแต่วันแรก ก่อนที่คุณจะเริ่มขัดแต่งป้ายและเลย์เอาต์\n\n## แนวทางพื้นฐานง่ายๆ ที่ทั้งทีมทำตามได้\n\nถ้าต้องการให้หน้าจอที่สร้างอัตโนมัติออกมาดูสะอาดตั้งแต่วันแรก ให้ตกลงแนวทางพื้นฐานก่อนจะมีใครเพิ่มตารางแรกเข้ามา ปัญหาการตั้งชื่อส่วนใหญ่ไม่ใช่เรื่องเทคนิค แต่เป็นปัญหาความสม่ำเสมอ\n\nเลือกสไตล์ตัวระบุหนึ่งแบบและอย่าผสมกัน สำหรับฐานข้อมูล snake_case มักอ่านง่ายและค้นหาได้สะดวก ถ้าสตั๊คของคุณต้องการ camelCase ก็ยึดตามนั้นทั้งระบบ (ตาราง คอลัมน์ foreign key enums) การสลับสไตล์กลางโปรเจ็กต์จะทำให้ป้ายและฟิลเตอร์ดูกระจัดกระจาย\n\nแนวทางพื้นฐานที่ใช้งานได้กับทีมส่วนใหญ่:\n\n- ใช้คำเต็ม: customer_id ไม่ใช่ cust_id; description ไม่ใช่ desc.\n- ใช้นามที่ชัดเจนสำหรับสิ่งต่าง ๆ และคำกริยาที่ชัดเจนสำหรับการกระทำ: invoice, payment, refund_requested.\n- ใช้ชื่อนามเวลาที่สอดคล้อง: created_at, updated_at, deleted_at.\n- หลีกเลี่ยงคำคลุมเครือเช่น data, info, value, หรือ type เว้นแต่ว่าจะเพิ่มบริบท (เช่น shipping_address, payout_method).\n- รักษาความสม่ำเสมอของเอกพจน์/พหูพจน์ (หลายทีมใช้ตารางพหูพจน์เช่น customers และคอลัมน์เอกพจน์เช่น customer_id).\n\nเขียนพจนานุกรมสั้น ๆ แล้วเก็บไว้ให้เห็นได้ง่าย ตัดสินใจตั้งแต่ต้นว่าคุณจะใช้คำว่า customer, client, account, หรือ user แล้วยึดตามคำเดียวกัน ทำแบบเดียวกันกับ “order” vs “purchase” หรือ “ticket” vs “case”.\n\nเช็คลิสต์อย่างง่าย: ถ้าสองคนดูคอลัมน์อย่าง account_status แล้วเข้าใจความหมายโดยไม่ต้องถาม แปลว่าแนวทางนี้ใช้ได้ ถ้าไม่ ให้เปลี่ยนชื่อก่อนจะสร้างหน้าจอและฟิลเตอร์ด้านบน\n\n## กฎการตั้งชื่อตารางที่แปลงไปเป็นเมนูและรายการได้ชัดเจน\n\nตารางส่วนใหญ่ในแอดมินจะกลายเป็นเมนู ชื่อรายการ และ breadcrumbs สกีมาไม่ได้มีไว้แค่นักพัฒนา แต่มันคือร่างแรกของ UI\n\nเลือกสไตล์เดียวสำหรับตารางเอนทิตีแล้วใช้ให้เท่ากัน: เอกพจน์ (user, invoice, ticket) หรือพหูพจน์ (users, invoices, tickets) เอกพจน์มักอ่านดีกว่าในชื่อฟอร์ม (“Edit Ticket”) ขณะที่พหูพจน์อาจดูดีกว่าในเมนู (“Tickets”) ทั้งสองแบบโอเค แต่การผสมทำให้การนำทางไม่สอดคล้อง\n\nตั้งชื่อตารางตามสิ่งที่มันเป็น ไม่ใช่ตามสิ่งที่มันทำ ตารางควรแทนสิ่งที่คุณชี้ไปได้ payment คือสิ่งหนึ่ง processing คือการกระทำ ถ้าคุณเพิ่ม refunds, retries, settlements ภายหลัง ชื่อว่า “processing” จะทำให้เข้าใจผิด\n\nกฎที่ช่วยให้เมนูและรายการสะอาด:\n\n- ใช้นามที่จับต้องได้ (customer, subscription, invoice, ticket_message).\n- หลีกเลี่ยงตารางกลุ่มสำหรับข้อมูลถาวร (settings, misc, temp, data) แยกเป็นเอนทิตีจริง (notification_setting, tax_rate, feature_flag).\n- ชื่อประกอบสั้น ๆ ที่อ่านง่ายโดยใช้ underscore (purchase_order, support_ticket) ดีกว่าตัวย่อ\n- เพิ่ม prefix โมดูลเฉพาะเมื่อป้องกันการชนกันได้เท่านั้น (เช่น billing_invoice vs invoice). ถ้าใช้ prefix ให้ใช้สม่ำเสมอในโมดูลนั้น\n\nถ้าคุณใช้ AppMaster เพื่อสร้างหน้าจอจากสกีมาโดยตรง ชื่อโต๊ะที่เป็นนามคงที่มักให้เมนูและมุมมองรายการเริ่มต้นที่สะอาดโดยต้องปรับน้อยครั้งต่อมา\n\n## ตารางเชื่อมและตัวระบุ: ทำให้ many-to-many อ่านง่าย\n\nความสัมพันธ์แบบ many-to-many เป็นจุดที่แผงแอดมินมักเริ่มดูรก ถ้าชื่อตารางเชื่อมและคีย์ตั้งได้ดี หน้าจอที่สร้างจะยังอ่านง่ายโดยไม่ต้องแก้ไขด้วยมือ\n\nเริ่มจากกฎน่าเบื่อข้อเดียวและอย่าล้มเลิก: ทุกตารางมี primary key ชื่อ id อย่าใช้ user_id เป็น primary key ในที่หนึ่งแล้วใช้ id ในอีกที่ ความสม่ำเสมอของตัวระบุทำให้ความสัมพันธ์คาดเดาได้และช่วยให้ฟอร์มและฟิลด์อ้างอิงที่สร้างอัตโนมัติสอดคล้องกัน\n\nสำหรับตาราง join ล้วน ตั้งชื่อตามทั้งสองเอนทิตีโดยใช้รูปแบบและลำดับเดียวกัน ตัวเลือกทั่วไปคือเรียงตามลำดับพยัญชนะ (product_tag) หรือ “สิ่งหลักก่อน” (user_role) เลือกลำดับหนึ่งแล้วใช้ทั่วทั้งระบบ\n\nหลีกเลี่ยงชื่อคลุมเครืออย่าง links หรือ mappings เว้นแต่ตารางนั้นเป็นการเก็บลิงก์ข้ามวัตถุแบบทั่วไปจริง ๆ ในแอดมินส่วนใหญ่ ความเฉพาะเจาะจงทำงานดีกว่าความคิดสร้างสรรค์\n\n### เมื่อ join table กลายเป็นเอนทิตีจริง\n\nถ้าความสัมพันธ์มีฟิลด์เพิ่ม ให้ถือเป็นโมเดลของตัวเองแล้วตั้งชื่อเป็นนามที่ผู้คนเข้าใจ เช่น membership, assignment, subscription ตัวอย่างเช่น ถาบทบาทของผู้ใช้มี starts_at, ends_at, และ granted_by user_role อาจโอเค แต่ membership อาจอ่านดีกว่าใน UI\n\nชุดกฎง่าย ๆ ที่ทำให้หน้าจอดูเป็นมืออาชีพ:\n\n- ใช้ id เป็น primary key ในทุกตาราง\n- ตั้งชื่อตาราง join ด้วยทั้งสองเอนทิตีในลำดับที่สอดคล้อง (user_role)\n- ใช้ foreign keys ชัดเจนเช่น user_id และ role_id\n- เพิ่มกฎความเป็นเอกลักษณ์ที่สอดคล้องกับความจริง (เช่น หนึ่ง role_id ต่อ user_id)\n- ถ้ารับประวัติ ให้ทำให้กฎความเป็นเอกลักษณ์สอดคล้องกับระเบียน “ที่ใช้งาน” (เช่น unique เมื่อ ended_at เป็น null)\n\nการเลือกเหล่านี้ทนทานเมื่อข้อมูลเติบโตและทำงานได้ดีกับ Data Designer ของ AppMaster ซึ่งสามารถสร้างหน้าจอโดยตรงจากโมเดล\n\n## รูปแบบการตั้งชื่อฟิลด์ที่ให้หัวคอลัมน์และฟิลเตอร์ที่ชัดเจน\n\nชื่อฟิลด์ไม่ใช่แค่ช่วยนักพัฒนา มันกำหนดสิ่งที่ผู้ใช้เห็นเป็นหัวคอลัมน์ ป้ายฟิลเตอร์ และช่องฟอร์ม\n\nคำลงท้ายที่คาดเดาได้จะลดการเดาได้:\n\n- ใช้ _id สำหรับ foreign keys: customer_id, assigned_agent_id.\n- ใช้ _at สำหรับ timestamps: created_at, paid_at, closed_at.\n- ใช้ _count สำหรับตัวนับ: login_count, attachment_count.\n\nค่า boolean ควรอ่านเหมือนประโยคธรรมดา ใช้ is_ และ has_ เพื่อให้ checkbox อ่านออกทันที: is_active, has_paid, is_verified. หลีกเลี่ยงคำปฏิเสธซ้อนอย่าง is_not_approved ถาต้องมีสถานะ “ไม่” ให้โมเดลสถานะเชิงบวกแล้วกลับตรรกะในโค้ดแทน\n\nฟิลด์เงินเป็นแหล่งความสับสนทั่วไปในกริดของแอดมิน เลือกแนวทางเดียวแล้วยึดตามมัน: เก็บหน่วยย่อย (เช่น เซนต์) เป็นจำนวนเต็ม หรือเก็บทศนิยมด้วยความแม่นยำคงที่ ตั้งชื่อฟิลด์ให้อ่านได้ทันที เช่น total_amount_cents + currency_code หรือ total_amount + currency_code อย่าผสม price, amount, total หากแต่ละคำมีความหมายต่างกัน\n\nฟิลด์ข้อความควรบอกจุดประสงค์ ไม่ใช่แค่ชนิด description เห็นได้ชัดต่อผู้ใช้ internal_comment เป็นส่วนตัว notes เป็นที่รวมข้อมูลทั่วไปและควรใช้อย่างระมัดระวัง ถ้ามีหลายโน้ต ให้ชื่อตามผู้รับ: customer_note, agent_note\n\nฟิลด์ติดต่อควรเรียกตามความเป็นจริงเพราะมันมักกลายเป็นฟิลเตอร์ด่วน: website_url, contact_email, billing_email ในหน้าจอที่สร้างโดย AppMaster ชื่อแบบนี้มักกลายเป็นป้ายเริ่มต้นที่ชัดเจน\n\n## ความสัมพันธ์และ foreign keys: ชื่อที่อธิบายโมเดลข้อมูล\n\nความสัมพันธ์ที่ดีอ่านเหมือนประโยคธรรมดา เมื่อแอดมินถูกสร้างจากฐานข้อมูล ชื่อ foreign key มักกลายเป็นหัวคอลัมน์ ฟิลเตอร์ และป้ายฟอร์ม\n\nรักษากฎข้อเดียว: คอลัมน์ foreign key คือชื่อตารางที่อ้างอิงบวกด้วย _id ถ้าคุณมี customer.id ให้ใช้ customer_id ถ้ามี order.id ให้ใช้ order_id ความสม่ำเสมอทำให้เห็นชัดว่าคอลัมน์ชี้ไปที่ไหน\n\nความสัมพันธ์ตัวเอง (self-relations) ต้องชัดกว่านี้เพราะอ่านผิดได้ง่าย หลีกเลี่ยง related_id แบบทั่วไป ใช้ชื่อที่อธิบายทิศทางและความหมาย เช่น parent_id สำหรับโครงสร้างแบบต้นไม้, manager_id สำหรับผังองค์กร, หรือ merged_into_id สำหรับการรวมข้อมูล\n\nเมื่อความสัมพันธ์ผ่านตาราง join ให้ตั้งชื่อให้อ่านเหมือนประโยค ตัวอย่างเช่น ticket_assignee.user_id ชัดเจนกว่า ticket_user.user_id ถ้าบทบาทคือ “assignee” (ไม่ใช่ “reporter” หรือ “watcher”)\n\nการตรวจสอบเชิงปฏิบัติที่ป้องกันปัญหาส่วนใหญ่:\n\n- อย่าใช้ owner_id ซ้ำกับความหมายต่างกันในตารางต่าง ๆ ให้ใช้ created_by_user_id, account_manager_user_id, หรือ billing_contact_id.\n- ถ้ามีหลายความสัมพันธ์ไปยังตารางเดียว ให้รวมบทบาทไว้: requested_by_user_id และ approved_by_user_id.\n- เลือกตัวบ่งชี้ soft delete เดียวและยึดตามมัน deleted_at เป็นที่เข้าใจกันโดยทั่วไปและใช้งานกับฟิลเตอร์ได้ดี\n\nถ้าคุณสร้างหน้าจอใน AppMaster ชื่อพวกนี้จะปรากฏทุกที่ ดังนั้นการใส่ใจเล็กน้อยในจุดนี้จะช่วยลดงานแก้ UI มาก\n\n## Enums และฟิลด์สถานะที่ยังเข้าใจได้เมื่อเวลาผ่านไป\n\nถ้าแผงแอดมินของคุณสร้างจากฐานข้อมูล วิธีที่เร็วที่สุดที่ทำให้หน้าจอดูรกคือกระจายความหมายไปในธงเล็ก ๆ จำนวนมาก ให้ใช้ enum สถานะเดียวที่ชัดเจนสำหรับวงจรชีวิตหลักของเรคคอร์ด และเก็บธงพิเศษไว้เฉพาะสำหรับพฤติกรรมที่ต่างกันจริง ๆ\n\nกฎที่มีประโยชน์: ถ้าผู้ใช้จะถามว่า “รายการนี้อยู่ในขั้นตอนไหนของกระบวนการ?” นั่นคือสถานะ ถ้าคำถามคือ “เราควรซ่อนมันไหม?” หรือ “มันล็อกอยู่หรือไม่?” นั่นคือ boolean แยกต่างหาก\n\n### สถานะเดียวดีกว่าห้า boolean\n\nแทนที่จะมี is_new, is_in_progress, is_done, is_cancelled ให้ใช้ ticket_status หนึ่งฟิลด์ มันอ่านดีกว่าในคอลัมน์รายการ ฟิลเตอร์ และการกระทำเป็นกลุ่ม และหลีกเลี่ยงความขัดแย้งอย่าง “done + in_progress”\n\nเก็บค่าของ enum ให้นิ่ง ป้าย UI สามารถเปลี่ยนได้ แต่ค่าที่เก็บไม่ควรเปลี่ยน เก็บ pending แทน waiting_for_review เก็บ rejected แทน rejected_by_manager คุณสามารถแสดงป้ายที่เป็นมิตรกว่าได้ทีหลังโดยไม่ต้องย้ายข้อมูล\n\nเมื่อจำเป็นต้องมีรายละเอียดเพิ่ม ให้เพิ่มฟิลด์ที่สองแทนการยัดทุกอย่างไว้ในสถานะ เช่น รักษา payment_status เป็นวงจรชีวิต แล้วเพิ่ม failure_reason (ข้อความ) เมื่อจำเป็น\n\n### ตั้งชื่อ enum ตามโดเมน (เพื่อให้ฟิลเตอร์เข้าใจได้)\n\nใช้ prefix โดเมนเพื่อให้หน้าจออ่านง่ายเมื่อหลายโมเดลมี “status”:\n\n- payment_status (กระบวนการเช็คเอาต์)\n- ticket_priority (ความเร่งด่วนฝ่ายสนับสนุน)\n- user_role (ระดับการเข้าถึง)\n- invoice_status (วงจรชีวิตการเรียกเก็บเงิน)\n- delivery_status (วงจรชีวิตการจัดส่ง)\n\nแยกวงจรชีวิตออกจากธงการดำเนินงาน เช่น: status อธิบายตำแหน่งในเวิร์กโฟลว์ ในขณะที่ is_archived หมายความว่าควรซ่อนไว้จากรายการประจำวัน\n\nเขียนความหมายหนึ่งประโยคสำหรับแต่ละค่าของ enum ในบันทึกทีมของคุณ คุณในอนาคตจะลืมความต่างระหว่าง cancelled กับ voided หากใช้ไม่ชัดเจน ถ้าคุณใช้ AppMaster คำอธิบายสั้น ๆ เหล่านี้ช่วยให้ dropdowns และฟิลเตอร์ที่สร้างอัตโนมัติคงที่ทั้งเว็บและมือถือ\n\n## กรณีพิเศษ: วันที่ ฟิลด์ตรวจสอบ และคอลัมน์ที่ชื่อว่า “type”\n\nแนวทางมักครอบคลุมตารางและฟิลด์พื้นฐาน แต่แผงแอดมินจะยุ่งในกรณีพิเศษ วันที่ ฟิลด์ตรวจสอบ และคอลัมน์ type คือจุดที่ชื่อที่สับสนทำให้หน้าจอสับสน\n\nสำหรับวันที่และ timestamp ให้ชื่อเล่าเรื่องว่าเป็นวันที่แบบไหน: วางแผน จริง หรือเตือน ตัวอย่างรูปแบบง่าย ๆ คือความหมายแบบกริยาบวกด้วยต่อท้ายที่ชัดเจน เช่น due_at (กำหนดเส้นตายที่วางแผนไว้) และ completed_at (วันที่เสร็จจริง) จะให้หัวคอลัมน์และฟิลเตอร์ที่เข้าใจได้ หลีกเลี่ยงคู่คำกว้าง ๆ อย่าง start_date และ end_date เมื่อคุณจริง ๆ หมายถึง scheduled_at และ finished_at\n\nความสัมพันธ์ที่เลือกได้ (optional relations) เป็นกับดักอีกแบบหนึ่ง อย่าคิดรูปแบบใหม่ตามแต่ละตาราง ให้ใช้ชื่อความสัมพันธ์คงที่และให้ความเป็น optional แสดงด้วยการยอมให้ null ไม่ใช่โดยการเปลี่ยนชื่อ manager_id ควรยังคงเป็น manager_id แม้ว่าจะเป็น optional\n\nที่อยู่ดูดีในโค้ดแต่รกในกริด หมายเลขบรรทัดรับได้ก็ต่อเมื่อทีมตกลงความหมายร่วมกัน ควรตั้งชื่อชัดเจน:\n\n- address_line1, address_line2, city, region, postal_code, country_code\n- หลีกเลี่ยง address1, address2 (อ่านยากกว่าและง่ายต่อการทำซ้ำ)\n\nฟิลด์ตรวจสอบควรน่าเบื่อโดยเจตนา:\n\n- created_at, updated_at\n- created_by_id, updated_by_id (เฉพาะเมื่อจริง ๆ จำเป็นต้องติดตามผู้ใช้)\n\nระวังการใช้ type มันมักกว้างเกินไปและใช้ได้ไม่ดีเมื่อเวลาผ่านไป แทนที่จะใช้ type ให้ตั้งชื่อความหมาย เช่น payment_method, ticket_channel, customer_tier ในสกีมาที่ขับเคลื่อนหน้าจอ (รวมถึง AppMaster) การเลือกชื่อเดียวนี้อาจเป็นความต่างระหว่างฟิลเตอร์ที่ชัดเจนและ dropdown ที่สับสน\n\n## ตัวอย่าง: ตั้งชื่อโมเดลตั๋วสนับสนุนให้ดูดีในแอดมิน\n\nการตั้งค่าเล็ก ๆ สมจริงสำหรับฝ่ายสนับสนุน: ลูกค้าเขียนเข้ามา เจ้าหน้าที่ตอบกลับ และตั๋วสามารถติดแท็กได้ แนวทางการตั้งชื่อช่วยให้เมนู มุมมองรายการ และฟิลเตอร์ที่สร้างอัตโนมัตรู้สึกชัดเจน\n\nเริ่มจากชื่อตารางที่อ่านเป็นนามในแถบด้านข้าง:\n\n- customer\n- ticket\n- ticket_message\n- ticket_tag\n- ticket_tag_link\n\nในแอดมิน ชื่อเหล่านี้มักกลายเป็นป้ายเช่น “Tickets” และ “Ticket Messages” และตารางเชื่อมมักไม่เด่นเกะกะ\n\nสำหรับหน้าจอรายการตั๋ว เลือกชื่อฟิลด์ที่จะเป็นหัวคอลัมน์และฟิลเตอร์ชัดเจน:\n\n- subject, status, priority\n- assigned_to_id (ชี้ไปยังผู้ใช้เจ้าหน้าที่)\n- last_message_at (ใช้เรียงลำดับตามความสด)\n- created_at (เป็นมาตรฐานและคาดเดาได้)\n\nEnums คือตรงที่ความอ่านง่ายมักแตกเมื่อเวลาผ่านไป ให้ชุดค่าที่นิ่งและเรียบง่าย:\n\n- ticket_status: new, open, pending_customer, resolved, closed\n- ticket_priority: low, normal, high, urgent\n\nการตัดสินใจตั้งชื่อหนึ่งอย่างที่ป้องกันความสับสนตลอดเวลา: อย่าใช้ “customer” ซ้ำความหมาย ในฝ่ายสนับสนุน ผู้ส่งคำร้องไม่เสมอเป็นลูกค้า (เพื่อนร่วมงานอาจส่งแทน) ถ้าคุณเก็บคนที่ส่งตั๋วไว้ ให้ตั้งชื่อ requester_id และแยก customer_id สำหรับบัญชีที่ตั๋วเกี่ยวข้อง การแยกนี้ทำให้ฟอร์มและฟิลเตอร์ตรงไปตรงมาตั้งแต่วันแรก\n\n## ขั้นตอนทีละขั้น: วิธีตั้งชื่อโมเดลใหม่ก่อนสร้างหน้าจอ\n\nวิธีที่ง่ายที่สุดในการรักษาหน้าจอให้อ่านง่ายคือ ตั้งชื่อขณะที่คุณยังคิดเป็นภาษาง่าย ๆ ไม่ใช่ตอนที่คุณกำลังสร้างแล้ว\n\n### กระบวนการที่ทำซ้ำได้สำหรับทุกฟีเจอร์\n\n1) เริ่มจากพจนานุกรมย่อ (5 ถึง 10 คำ) เขียนคำที่เพื่อนร่วมงานไม่เชิงเทคนิคจะใช้ในการประชุม แล้วเลือกคำเดียวที่ใช้แทนแต่ละแนวคิด (เช่น “customer” vs “client”).\n\n2) สเก็ตช์หน้าจอที่คาดว่าจะมี: list, detail, create, edit สำหรับมุมมองรายการ ให้ตัดสินใจว่าทั้ง 5 ถึง 8 คอลัมน์ที่ต้องชัดเจนคืออะไร ถ้าชื่อฟิลด์จะดูแปลกเป็นหัวคอลัมน์ นั่นอาจต้องแก้\n\n3) ร่างตารางและความสัมพันธ์ แล้วตั้งชื่อฟิลด์โดยใช้กฎต่อท้าย (*_id, *_at, is_*, *_count). เมื่อคุณสร้างหน้าจออัตโนมัติ (รวมถึงใน AppMaster) รูปแบบเหล่านี้มักให้ป้ายและฟิลเตอร์เริ่มต้นที่สะอาดและคาดเดาได้\n\nก่อนจะไปต่อ ให้แน่ใจว่าคุณไม่ผสมสไตล์ (customer_id ในที่หนึ่ง, clientId ในอีกที่) ความสม่ำเสมอชนะความฉลาด\n\n4) กำหนด enum แต่เนิ่น ๆ ไม่ใช่หลังจากมี UI ตัวแรกแล้ว เขียนความหมายหนึ่งบรรทัดสำหรับแต่ละค่า เหมือนอธิบายให้ฝ่ายซัพพอร์ต ฟิลด์ค่าที่ทนทานเช่น pending, active, archived ดีกว่า new, newer, newest\n\n5) ทำ “อ่านหัวคอลัมน์” ลองนึกถึงตัวเองเป็นผู้ใช้แอดมินที่สแกนตาราง\n\n- จะเข้าใจ “Created At”, “Updated At”, “Status”, “Assigned To”, “Total Amount” โดยไม่ต้องอบรมไหม?\n- ฟิลด์ใดดูเหมือนรหัสภายใน (tmp_flag, x_type, data1)?\n- หน่วยชัดเจนหรือไม่ (amount_cents vs amount, duration_seconds vs duration)?\n\nถ้าหมายความอะไรไม่ชัดเมื่ออ่านออกเสียง ให้เปลี่ยนชื่อเดี๋ยวนั้น การเปลี่ยนชื่อต่อมาทำได้แต่บ่อยครั้งจะรั่วเข้าไปในรายงาน ฟิลเตอร์ และพฤติกรรมการใช้งาน\n\n## ความผิดพลาดที่พบบ่อยซึ่งทำให้แผงแอดมินใช้งานยาก\n\nถ้าสกีมาเละ หน้าจอก็จะเละแม้ UI จะสวย การตั้งชื่อเป็นเรื่องความสามารถในการใช้งานประจำวันมากกว่าแค่สไตล์\n\nกับดักแรกคือคำศัพท์ผสม หากที่หนึ่งใช้ client และอีกที่ใช้ customer เมนู ฟิลเตอร์ และผลการค้นหาจะดูเหมือนกำลังพูดถึงสิ่งต่างกัน เลือกคำเดียวสำหรับแต่ละแนวคิดหลักแล้วใช้อย่างสม่ำเสมอ รวมถึงชื่อความสัมพันธ์ด้วย\n\nปัญหาทั่วไปอีกประการคือย่อสั้นเกินไป อักษรย่อเช่น addr, misc, หรือ info อาจประหยัดตัวอักษรแต่ลดความชัดเจนในการดูตารางและส่งออกข้อมูล\n\nข้อผิดพลาดที่สามคือการฝังลำดับการใช้งานของ UI ลงไปในฐานข้อมูล ฟิลด์อย่าง new_customer_wizard_step เหมาะตอนเปิดตัว แต่จะงงเมื่อเปลี่ยน flow หรือเพิ่มเส้นทาง onboarding ใหม่ ให้เก็บข้อเท็จจริงทางธุรกิจ (เช่น onboarding_status) แล้วให้ UI เป็นคนตัดสินวิธีแนะนำผู้ใช้\n\nระวัง boolean ที่เยอะเกินไป เมื่อเพิ่ม is_new, is_open, is_closed สุดท้ายจะเกิดความขัดแย้ง (สองค่า true พร้อมกัน) และฟิลเตอร์ไม่ชัดเจน ให้ใช้ฟิลด์สถานะเดียวที่ชุดค่าน้อยและชัดเจน\n\nสัญญาณเตือนที่มักนำไปสู่หน้าจอแย่ ๆ:\n\n- ใช้สองชื่อนัยเดียวกัน (client_id ที่หนึ่ง, customer_id อีกที่)\n- คอลัมน์รวบรวม (notes, misc, extra) ที่ใส่ข้อมูลผสมกัน\n- ชื่อที่ผูกกับช่วงเวลา (summer_campaign_*) ที่มีอายุการใช้งานยาวเกินไป\n- หลาย boolean ที่พยายามบรรยายสถานะเดียว\n- การเปลี่ยนชื่ออย่างสุ่มสี่สุ่มห้าโดยไม่มีแผนย้ายข้อมูล\n\nการเปลี่ยนชื่อไม่ใช่แค่ค้นหาแล้วแทนที่ ถ้าคุณเปลี่ยน customer_phone เป็น phone_number ให้วางแผนการย้ายข้อมูล อัปเดตหน้าจอที่สร้าง และรักษาความเข้ากันได้ย้อนหลังเมื่อจำเป็น โดยเฉพาะถ้าระบบอื่นเรียก API ของคุณ ใน AppMaster ชื่อที่สะอาดให้ผลทันทีเพราะรายการ ฟอร์ม และฟิลเตอร์รับป้ายเหล่านี้จากโมเดลของคุณ\n\n## เช็คลิสต์ด่วนก่อนปล่อยแผงแอดมิน\n\nก่อนจะเรียกว่าสกีมา “เสร็จ” ให้ทำการตรวจจากมุมมองคนที่ใช้แอดมินทุกวัน\n\n- ตารางเป็นสิ่งที่จับต้องได้. เพื่อนร่วมงานควรบอกได้ว่าตารางแทนอะไร (ticket, customer, invoice) โดยไม่ต้องเดา\n- ฟิลด์สำคัญใช้ต่อท้ายที่คาดเดาได้. ใช้รูปแบบที่คนรู้จักทันที: *_id สำหรับอ้างอิง, *_at สำหรับ timestamp, *_amount (หรือ *_amount_cents) สำหรับเงิน, และ is_* สำหรับธงจริง/เท็จ\n- Enums คงที่และเรียบง่าย. เก็บค่าเช่น pending, paid, failed แทนวลีใน UI ที่อาจเปลี่ยน\n- เพื่อนร่วมงานใหม่สามารถสรุปความหมายได้. ถ้าฟิลด์โผล่ในมุมมองรายการที่สร้างอัตโนมัติโดยไม่มีข้อความช่วยเหลือ ความหมายยังจะชัดไหม?\n- คำกำกวมถูกลบหรือทำให้เฉพาะเจาะจง. แทนที่ชื่อลิ้นชักอย่าง data, value, type, หรือ info ด้วยชื่อชัดเจนเช่น status, source, category, notes, หรือ external_reference\n\nถ้าคุณใช้ Data Designer ของ AppMaster เพื่อสร้างมุมมองแบบแอดมินจากสกีมา เช็คลิสต์นี้ใช้งานได้จริงทันที: ชื่อชัดเจนกลายเป็นคอลัมน์และฟิลเตอร์ที่ชัดเจน และคุณจะใช้เวลาน้อยลงในการแก้ป้ายหลังจากผู้ใช้เริ่มใช้งานระบบ\n\n## ขั้นตอนต่อไป: ทำให้การตั้งชื่อเป็นนิสัย (และรักษาหน้าจอให้สม่ำเสมอ)\n\nการตั้งชื่อที่ดีไม่ใช่การทำครั้งเดียว แต่นิสัยเล็ก ๆ ที่รักษา UI ให้อ่านง่ายเมื่อสกีมาโตขึ้น\n\nเริ่มจากโมดูลหนึ่งที่มีอยู่แล้วและใช้กฎกับตารางใหม่ที่คุณจะเพิ่ม วิธีนี้หลีกเลี่ยงการเขียนทับครั้งใหญ่และให้ที่ฝึกจริง ๆ ถ้าฟีเจอร์ถัดไปของคุณเพิ่ม “returns” ในระบบคำสั่ง ให้ตั้งชื่อตาราง foreign keys และสถานะโดยใช้รูปแบบของคุณตั้งแต่วันแรก แล้วนำแนวทางไปใช้กับฟีเจอร์ถัดไป\n\nเก็บคู่มือการตั้งชื่อหน้าเดียวไว้ใกล้กับที่คุณทำงานกับสกีมา ให้สั้น ๆ: วิธีตั้งชื่อตาราง primary keys foreign keys timestamps และ status enums เป้าหมายคือตัดสินใจเร็ว ไม่ใช่ถกเถียงยาวนาน\n\nถ้าคุณพัฒนาโดยใช้ AppMaster การตั้งรูปแบบเหล่านี้ใน Data Designer ก่อนแตะ UI จะช่วยได้มาก เมื่อคุณเปลี่ยนชื่อตารางหรือฟิลด์ ให้ regenerate แอปเพื่อให้หน้าจอ API และ logic อยู่ในแนวเดียวกันแทนที่จะลอยไปคนละทาง\n\nขั้นตอนทบทวนเบา ๆ ก่อนแต่ละรีลีสมักเพียงพอ:\n\n- ชื่อตารางและฟิลด์อ่านดีเป็นเมนู หัวคอลัมน์ และฟิลเตอร์หรือไม่?\n- สถานะและ enums ชัดเจนโดยไม่ต้องคำอธิบายเพิ่มเติมหรือไม่?\n- ความสัมพันธ์และ foreign keys อธิบายตัวเองไหม (ไม่ใช่ตัวย่อลึกลับ)?\n- โมเดลที่คล้ายกันตั้งชื่อสอดคล้องกันไหม (คำเดียวกัน ลำดับเดียวกัน)?\n\nเมื่อเวลาผ่านไป ผลลัพธ์จริงคือความสม่ำเสมอ เมื่อทุกโมเดลใหม่ปฏิบัติตามกฎเดียวกัน แผงแอดมินของคุณจะเริ่มดูเหมือนออกแบบมา แม้จะถูกสร้างอัตโนมัติก็ตาม เพราะป้ายและรายการอ่านเป็นผลิตภัณฑ์ที่สอดคล้องกัน
คำถามที่พบบ่อย
ใช้ชื่อที่อ่านว่าเรากำลังอธิบายสิ่งที่ระเบียนเป็น ไม่ใช่ว่ามันกำลังทำอะไร ตารางที่ชื่อว่า ticket หรือ invoice จะกลายเป็นเมนูที่ชัดเจน ขณะที่ชื่ออย่าง processing มักสับสนเมื่อขั้นตอนงานเปลี่ยนไป
เลือกสไตล์เดียวแล้วยึดตามนั้นตลอด สำหรับฐานข้อมูลโดยทั่วไป snake_case มักอ่านง่ายและทำให้ป้ายชื่อและฟิลเตอร์ที่สร้างอัตโนมัติออกมาสม่ำเสมอ
โดยดีฟอลต์ใช้คำเต็มและชัดเจน เพราะมันจะกลายเป็นหัวคอลัมน์และป้ายฟิลเตอร์ ย่อคำอย่าง acct หรือ addr1 มักทำให้ผู้ปฏิบัติงานต้องถอดความ แม้ผู้พัฒนาจะเข้าใจ
เลือกระหว่างรูปพหูพจน์หรือเอกพจน์แล้วใช้ให้ตรงกันทั่วทั้งโปรเจ็กต์ ตัวอย่างเช่น ticket หรือ tickets ก็ได้ แต่ไม่ควรผสมทั้งสองแบบ
กฎง่าย ๆ คือ ให้ใช้ id เป็น primary key ของทุกตาราง และใช้ foreign key แบบ something_id วิธีนี้ทำให้ความสัมพันธ์คาดเดาได้และฟอร์มที่สร้างโดยระบบดูสอดคล้องกัน
สำหรับตาราง join ล้วนให้ตั้งชื่อตามทั้งสองเอนทิตีตามรูปแบบเดียวกัน เช่น user_role หรือ product_tag หากความสัมพันธ์มีฟิลด์เพิ่มเติมและมีความหมายของตัวเอง ให้ตั้งชื่อเป็นนามธรรม เช่น membership หรือ assignment เพื่อให้ UI อ่านได้เป็นธรรมชาติ
ใช้คำลงท้ายที่คาดเดาได้ตามประเภทข้อมูล เช่น _at สำหรับ timestamp, _count สำหรับเคาน์เตอร์ สำหรับ boolean ให้ใช้ is_ หรือ has_ เพื่อให้ checkbox อ่านเป็นประโยคได้ทันทีในหน้าจอที่สร้างอัตโนมัติ
เลือกฟิลด์สถานะเดียวที่ชัดเจนสำหรับวงจรชีวิตหลัก เช่น ticket_status หรือ invoice_status แทนหลาย boolean ที่อาจขัดแย้งกัน เก็บค่าที่บันทึกให้ไม่ผูกกับคำแสดงผล เพื่อจะเปลี่ยนป้ายได้โดยไม่ต้องย้ายข้อมูล
หลีกเลี่ยงชื่อทั่วไปอย่าง owner_id หรือ type เมื่อมีความหมายต่างกันในแต่ละตาราง ให้ใช้ชื่อที่บอกบทบาทชัดเจน เช่น created_by_user_id, approved_by_user_id, หรือ payment_method เพื่อให้ฟิลด์และฟิลเตอร์อธิบายตัวเองได้
ควรเปลี่ยนชื่อในช่วงต้นก่อนที่หน้าจอ ฟิลเตอร์ และรายงานจะพึ่งพาคำเดิม ใน AppMaster ให้แก้ชื่อใน Data Designer แล้ว regenerate แอป เพื่อให้ UI และ API สอดคล้องกันและไม่เบี้ยวตามเวลา


