PlusMagi's Blog By Pitt Phunsanit Backend,Database Clean Architecture: Anemic Domain Model

Clean Architecture: Anemic Domain Model

ในโลกของการพัฒนาระบบซอฟต์แวร์ การออกแบบสถาปัตยกรรมที่แข็งแกร่งเป็นสิ่งสำคัญยิ่ง 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 และใช้ประโยชน์จากพลังของฐานข้อมูลเชิงสัมพันธ์อย่างสูงสุด

Exit mobile version