ในโลกของการพัฒนาระบบซอฟต์แวร์ การออกแบบสถาปัตยกรรมที่แข็งแกร่งเป็นสิ่งสำคัญยิ่ง Clean Architecture คือแนวคิดที่มุ่งเน้นการแยกส่วนประกอบทางธุรกิจ (Domain) ออกจากรายละเอียดทางเทคนิค (เช่น ฐานข้อมูล, UI) อย่างชัดเจน อย่างไรก็ตาม การทำความเข้าใจเรื่อง Clean Architecture ไม่ได้หมายความว่าเราจะสามารถหลีกเลี่ยงปัญหาที่เรียกว่า Anemic Domain Model ได้โดยง่าย
Anemic Domain Model คืออะไร?
Anemic Domain Model คือรูปแบบที่ Object Model ของเรามีเพียงแค่ตัวแปร (Attributes) แต่ขาดพฤติกรรม (Behavior) หรือ Business Logic ที่สำคัญ ตัวอย่างเช่น คลาส `User` อาจมีแค่ฟิลด์ `name` และ `email` แต่ถ้าการตรวจสอบว่าผู้ใช้มีสิทธิ์เปลี่ยนสถานะต้องผ่านการคำนวณที่ซับซ้อน Logic เหล่านั้นมักจะถูกโยนกลับไปที่ Service Layer หรือ Repository Layer แทนที่จะอยู่ใน Domain Model เอง
การใช้ PostgreSQL เพื่อเสริมความแข็งแกร่งของ Domain Logic
เมื่อเราใช้ PostgreSQL เป็นระบบฐานข้อมูลหลัก เราสามารถใช้คุณสมบัติขั้นสูงของมัน เช่น Stored Procedures, Functions, และ Triggers เพื่อย้าย Business Logic ที่สำคัญเหล่านั้นกลับไปที่ชั้น Persistence Layer ได้อย่างมีประสิทธิภาพ นี่คือการเปลี่ยนบทบาทของ PostgreSQL จากการเป็นเพียงที่เก็บข้อมูล (Data Store) ให้กลายเป็นส่วนหนึ่งของการบังคับใช้กฎทางธุรกิจ (Domain Enforcement Layer) ซึ่งเป็นหัวใจสำคัญในการหลีกหนีจาก Anemic Model
ตัวอย่างการใช้ PostgreSQL Function
สมมติว่าเรามีตาราง `products` และเราต้องการให้การอัปเดตสถานะสินค้า (Status) สามารถทำได้ก็ต่อเมื่อสินค้ามีราคาสูงกว่า 100 บาทเท่านั้น การเขียน Logic นี้ใน Application Code อาจทำให้เกิดช่องโหว่ได้ แต่การฝังไว้ใน PostgreSQL Function จะรับประกันความถูกต้องของข้อมูลเสมอ
SQL
-- สร้างตารางสินค้าพื้นฐาน (Product Table)
SQL
CREATE TABLE products (
SQL
product_id SERIAL PRIMARY KEY,
SQL
name VARCHAR(255) NOT NULL,
SQL
price NUMERIC(10, 2) NOT NULL,
SQL
status VARCHAR(50) DEFAULT 'draft'
SQL
);
เราจะสร้างฟังก์ชันที่รับผิดชอบการอัปเดตสถานะสินค้า โดยมีเงื่อนไขทางธุรกิจ (Business Rule) ฝังอยู่:
SQL
CREATE OR REPLACE FUNCTION update_product_status(
SQL
p_product_id INT,
SQL
p_new_status VARCHAR(50)
SQL
) RETURNS BOOLEAN AS $$
SQL
BEGIN
SQL
-- Business Rule: ต้องมีราคาสูงกว่า 100 บาทจึงจะเปลี่ยนสถานะเป็น 'published' ได้
SQL
IF p_new_status = 'published' AND (SELECT price FROM products WHERE product_id = p_product_id) < 100 THEN
SQL
RAISE EXCEPTION 'Product must cost more than 100 to be published.';
SQL
END IF;
SQL
UPDATE products
SQL
SET status = p_new_status
SQL
WHERE product_id = p_product_id;
SQL
RETURN TRUE;
SQL
END;
SQL
$$ LANGUAGE plpgsql;
การเรียกใช้ฟังก์ชัน
เมื่อ Application Layer เรียกใช้ฟังก์ชันนี้ ข้อมูลจะถูกตรวจสอบตามกฎที่กำหนดไว้ใน PostgreSQL ทันที:
SQL
-- ตัวอย่างการเรียกใช้ที่ถูกต้อง (Product ID 1 ราคา 200)
SQL
SELECT update_product_status(1, 'published');
SQL
-- ตัวอย่างการเรียกใช้ที่ผิดพลาด (Product ID 2 ราคา 50)
SQL
SELECT update_product_status(2, 'published'); -- จะเกิด Exception
บทสรุป
การผสาน Clean Architecture เข้ากับความสามารถของ PostgreSQL อย่างเต็มรูปแบบ ทำให้เราสามารถยกระดับชั้น Persistence ให้ทำหน้าที่เป็น Domain Logic Enforcer ได้อย่างแท้จริง การใช้ Stored Procedures และ Functions ไม่เพียงแต่ช่วยให้โค้ดมีความปลอดภัยและเป็น Atomic Transaction เท่านั้น แต่ยังช่วยให้ Business Rules ถูกรวมศูนย์ (Centralized) อยู่ในที่เดียว ทำให้ระบบมีความทนทานและง่ายต่อการบำรุงรักษาในระยะยาว นี่คือการออกแบบที่สมบูรณ์แบบที่ลดการพึ่งพา Anemic Model และใช้ประโยชน์จากพลังของฐานข้อมูลเชิงสัมพันธ์อย่างสูงสุด