ป้ายกำกับ: DDD

Clean Architecture: Package by Feature vs Package by LayerClean Architecture: Package by Feature vs Package by Layer

ในฐานะสถาปนิกระบบที่ทำงานกับฐานข้อมูล PostgreSQL ขนาดใหญ่ การเลือกโครงสร้างแพ็กเกจ (Package Structure) ที่เหมาะสมเป็นสิ่งสำคัญอย่างยิ่งในการรักษาความยืดหยุ่น (Maintainability) และความสามารถในการขยายตัว (Scalability) ของระบบ Clean Architecture ไม่ได้จำกัดแค่โค้ดแอปพลิเคชันเท่านั้น แต่ยังรวมถึงการออกแบบโครงสร้างฐานข้อมูลด้วย

บทความนี้จะเจาะลึกการเปรียบเทียบระหว่างการจัดโครงสร้างแบบ ‘Package by Feature’ และ ‘Package by Layer’ โดยเน้นการประยุกต์ใช้หลักการเหล่านี้ให้สอดคล้องกับระบบนิเวศของ PostgreSQL โดยเฉพาะ

🧱 Package by Layer: การจัดโครงสร้างตามชั้นทางเทคนิค

แนวคิดนี้คือการจัดกลุ่มโค้ดและตารางทั้งหมดตามหน้าที่ทางเทคนิค (Technical Concern) เช่น การแยก Schema สำหรับ `data_access`, `business_logic`, หรือ `api` การออกแบบนี้ทำให้โค้ดดูเป็นระเบียบตามประเภทของงาน แต่มีข้อเสียคือเมื่อฟีเจอร์ใหม่เข้ามา การเปลี่ยนแปลงอาจส่งผลกระทบข้าม Schema ได้ง่าย ทำให้เกิดการพึ่งพา (Coupling) สูง

SQL

-- ตัวอย่าง Package by Layer (Schema Monolith) --
CREATE SCHEMA data_access;
CREATE SCHEMA business_logic;

-- ตาราง Order อยู่ใน Layer Data Access
CREATE TABLE data_access.orders (order_id SERIAL PRIMARY KEY, item_list TEXT);

-- โลจิกธุรกิจก็ยังต้องเรียกใช้ตารางจาก Layer อื่น
-- SELECT * FROM data_access.orders WHERE order_id = 1;

🚀 Package by Feature: การจัดโครงสร้างตามโดเมนธุรกิจ (Recommended)

Package by Feature คือการจัดกลุ่มโค้ดและองค์ประกอบทั้งหมดที่เกี่ยวข้องกับโดเมนธุรกิจใดโดเมนหนึ่ง (เช่น การจัดการผู้ใช้, การสั่งซื้อ) ให้อยู่รวมกันในหน่วยเดียว การใช้ PostgreSQL Schema ช่วยให้เราสามารถจำลองการแยกแพ็กเกจนี้ได้อย่างมีประสิทธิภาพ โดยแต่ละ Schema จะเป็นตัวแทนของฟีเจอร์หลัก ทำให้เกิดการแยกส่วน (Decoupling) ที่ชัดเจนที่สุด

เมื่อระบบเติบโตขึ้น การเพิ่มฟีเจอร์ใหม่ทำได้ง่ายเพียงแค่สร้าง Schema ใหม่ ไม่ต้องไปแตะต้อง Schema ของฟีเจอร์อื่น ๆ เลย

SQL

-- ตัวอย่าง Package by Feature (Schema Isolation) --
-- 1. สร้าง Schema สำหรับฟีเจอร์ User Management
CREATE SCHEMA user_management;

-- 2. สร้าง Schema สำหรับฟีเจอร์ Order Processing
CREATE SCHEMA order_processing;

-- 3. ตาราง User อยู่ใน Schema ของ User
CREATE TABLE user_management.users (user_id SERIAL PRIMARY KEY, username TEXT);

-- 4. ตาราง Order อยู่ใน Schema ของ Order
CREATE TABLE order_processing.orders (order_id SERIAL PRIMARY KEY, user_id INT REFERENCES user_management.users(user_id));

💡 บทสรุป: การเลือกสถาปัตยกรรมที่เหมาะสม

สำหรับระบบที่คาดว่าจะมีการเติบโตและมีโดเมนธุรกิจที่หลากหลาย การใช้ **Package by Feature** คือแนวทางที่เหนือกว่าอย่างชัดเจน เพราะมันช่วยให้เกิดการแยกส่วน (Isolation) ในระดับ Schema ของ PostgreSQL ทำให้การพัฒนาและการบำรุงรักษามีความเสี่ยงต่ำ (Low Coupling) และทีมงานสามารถทำงานขนานกันในแต่ละฟีเจอร์ได้อย่างอิสระ การออกแบบนี้สอดคล้องกับหลักการของ Clean Architecture ที่เน้นให้ธุรกิจเป็นศูนย์กลาง (Domain Driven Design) อย่างแท้จริง