ในการพัฒนาซอฟต์แวร์เชิงวัตถุ (OOP) ปัญหาที่พบบ่อยและอันตรายที่สุดคือ Unexpected Mutation หรือการที่ข้อมูลถูกเปลี่ยนแปลงโดยไม่คาดคิด ซึ่งเป็นสาเหตุหลักของบั๊กที่แก้ไขยากมาก
แนวคิดในการแก้ปัญหานี้คือการสร้าง Immutable Object หรือ Object ที่ไม่สามารถเปลี่ยนแปลงสถานะภายในได้หลังจากถูกสร้างขึ้นมาแล้ว (Read-only) ในระดับแอปพลิเคชัน PHP ได้เพิ่มฟีเจอร์ Readonly Properties (PHP 8.1) และ Readonly Classes (PHP 8.2) เพื่อช่วยให้โค้ดมีความปลอดภัยมากขึ้น
การบังคับใช้ความคงที่ของข้อมูลในระดับฐานข้อมูล (PostgreSQL)
แม้ว่า PHP จะช่วยให้เราสร้าง Object ที่อ่านได้อย่างเดียว แต่การป้องกันข้อมูลผิดพลาดที่ต้นทาง (Source of Truth) อย่างฐานข้อมูลนั้นสำคัญไม่แพ้กัน ในฐานะ Senior Architect เราต้องมั่นใจว่าข้อมูลของเราถูกบังคับให้เป็นไปตามกฎเกณฑ์เสมอ ไม่ว่าแอปพลิเคชันชั้นใดจะเรียกใช้
สำหรับ PostgreSQL เราไม่จำเป็นต้องใช้โค้ดที่ซับซ้อนเพื่อจำลองการเป็น Read-only แต่เราใช้คุณสมบัติของฐานข้อมูล เช่น CHECK Constraints หรือ ENUM Types เพื่อกำหนดขอบเขตของข้อมูลที่อนุญาตให้บันทึกได้ นี่คือการบังคับใช้ความคงที่ในระดับโครงสร้างข้อมูล (Schema Level) ซึ่งแข็งแกร่งกว่าการป้องกันในระดับโค้ดแอปพลิเคชัน
ตัวอย่าง: การจำกัดสถานะสินค้า (Status)
สมมติว่าเรามีตารางสินค้าที่สถานะ (Status) ต้องเป็นค่าที่กำหนดไว้เท่านั้น เช่น ‘Draft’, ‘Active’, หรือ ‘Archived’ เราสามารถใช้ ENUM type ของ PostgreSQL เพื่อจำกัดค่าที่อนุญาตให้บันทึกได้ ทำให้ข้อมูลที่เข้ามาในระบบเป็นไปตามกฎเกณฑ์เสมอ
SQL
SQL
-- 1. สร้าง ENUM Type เพื่อจำกัดสถานะที่อนุญาตให้มีได้เท่านั้น (Read-only set of values)
CREATE TYPE product_status AS ENUM ('Draft', 'Active', 'Archived');
-- 2. สร้างตารางสินค้า โดยใช้ ENUM type นี้
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
status product_status NOT NULL
);
-- 3. ตัวอย่างการ INSERT ข้อมูลที่ถูกต้อง
INSERT INTO products (name, status) VALUES ('Laptop X', 'Active');
-- 4. ตัวอย่างการพยายาม INSERT ข้อมูลที่ผิด (จะเกิด Error เพราะ 'Pending' ไม่อยู่ใน ENUM type)
-- INSERT INTO products (name, status) VALUES ('Monitor Y', 'Pending');
การใช้ CHECK Constraints เพื่อความสมบูรณ์ของข้อมูล
นอกจากนี้ เรายังสามารถใช้ CHECK Constraints เพื่อกำหนดเงื่อนไขทางธุรกิจที่ซับซ้อนขึ้นได้ เช่น หากสินค้ามีราคาน้อยกว่า 10 บาท จะต้องถูกตั้งสถานะเป็น ‘Draft’ เสมอ
SQL
SQL
ALTER TABLE products
ADD CONSTRAINT check_price_status
CHECK (CASE WHEN price < 10 THEN status = 'Draft' ELSE TRUE END);
-- หมายเหตุ: ในการใช้งานจริง ควรเพิ่มคอลัมน์ 'price' เข้าไปในตารางด้วย
บทสรุป: การป้องกันข้อมูลที่หลายชั้น
การสร้าง Object ที่เป็น Immutable ใน PHP ช่วยให้โค้ดมีความเสถียรในระดับแอปพลิเคชัน ในขณะที่การใช้ ENUM และ CHECK Constraints ใน PostgreSQL ช่วยให้มั่นใจว่าข้อมูลที่ถูกบันทึกในฐานข้อมูลนั้นถูกต้องตามกฎเกณฑ์ทางธุรกิจอย่างเคร่งครัด
การรวมกันของแนวคิดเหล่านี้ (Immutability ใน OOP และ Constraints ใน Database) คือหลักการสำคัญของการออกแบบระบบที่แข็งแกร่งและเชื่อถือได้ในระดับ Senior Architect ครับ