PlusMagi's Blog By Pitt Phunsanit Backend,Database Clean Architecture: Use Case Input/Output Ports

Clean Architecture: Use Case Input/Output Ports

ในโลกของการพัฒนาระบบที่ซับซ้อน การรักษาความยืดหยุ่นและการแยกส่วนประกอบ (Decoupling) คือหัวใจสำคัญของสถาปัตยกรรมซอฟต์แวร์ Clean Architecture คือแนวทางที่ช่วยให้แอปพลิเคชันของเราเป็นอิสระจากรายละเอียดทางเทคนิคภายนอก เช่น ฐานข้อมูลหรือ UI การทำความเข้าใจเรื่อง Use Case Input/Output Ports จึงเป็นสิ่งจำเป็นสำหรับ Senior Architect ที่ต้องการสร้างระบบที่ทนทานและง่ายต่อการบำรุงรักษา

Ports ในบริบทของ PostgreSQL

ใน Clean Architecture, Use Case Ports ทำหน้าที่เป็นสัญญา (Contract) ที่กำหนดว่า Use Case นั้นๆ ต้องการข้อมูลอะไรจากโลกภายนอก (Input Port) และจะส่งผลลัพธ์อะไรกลับไป (Output Port) เมื่อเราใช้ PostgreSQL เป็นระบบหลัก เราสามารถจำลอง Ports เหล่านี้ได้โดยการใช้ฟังก์ชันที่ถูกกำหนดพารามิเตอร์อย่างชัดเจน (Parameterized Functions) และการใช้ประเภทข้อมูลที่ซับซ้อน (Complex Data Types) เช่น `JSONB` หรือ `TEXT[]` เพื่อบังคับใช้รูปแบบข้อมูลที่ Use Case ต้องปฏิบัติตาม

การจำลอง Input Port ด้วย PostgreSQL Functions

Input Port คือจุดที่ Use Case รับข้อมูลเข้า ฟังก์ชันใน PostgreSQL จะทำหน้าที่เป็นตัวรับ Input นี้ โดยเราจะกำหนด Signature ของฟังก์ชันให้ตรงกับข้อมูลที่ Use Case คาดหวัง ตัวอย่างเช่น หาก Use Case ต้องการประมวลผลรายการ ID ผู้ใช้ที่ถูกคั่นด้วยเครื่องหมายคอมมา เราควรใช้ประเภทข้อมูล Array ของ PostgreSQL เพื่อรับประกันความถูกต้องของข้อมูล

SQL

-- 1. สร้างตารางจำลองข้อมูล (Repository Layer)

SQL

CREATE TABLE users (user_id TEXT PRIMARY KEY, username TEXT, status TEXT);

ต่อไปนี้คือการสร้างฟังก์ชันที่ทำหน้าที่เป็น ‘Use Case’ ซึ่งมี Input Port ที่รับ Array ของ User IDs:

SQL

-- 2. สร้างฟังก์ชันที่ทำหน้าที่เป็น Use Case (Input Port Contract)

SQL

CREATE OR REPLACE FUNCTION process_user_batch(user_ids TEXT[])

SQL

RETURNS TABLE (user_id TEXT, processed_status TEXT)

SQL

LANGUAGE plpgsql

SQL

AS $$

SQL

BEGIN

SQL

RETURN QUERY

SQL

SELECT

SQL

user_id,

SQL

'SUCCESS'

SQL

FROM unnest(user_ids) AS un(user_id)

SQL

JOIN users ON users.user_id = un.user_id;

SQL

END;

SQL

$$;

การเรียกใช้ Use Case (Testing the Input Port)

เมื่อเราเรียกใช้ฟังก์ชันนี้ เรากำลังปฏิบัติตามสัญญาของ Input Port โดยการส่ง Array ของ ID ที่ถูกต้อง:

SQL

SELECT * FROM process_user_batch('101'::text, '102'::text, '103'::text');

บทสรุป

การใช้ PostgreSQL Functions ที่มี Signature ชัดเจนช่วยให้เราสามารถจำลอง Use Case Ports ได้อย่างมีประสิทธิภาพ สิ่งนี้ช่วยให้โค้ดของเรามีความเป็นโมดูลสูง (Highly Modular) และที่สำคัญที่สุดคือทำให้เราสามารถทดสอบ Use Case ได้อย่างอิสระ (Testability) โดยไม่จำเป็นต้องพึ่งพาการทำงานของส่วนประกอบอื่น ๆ ทำให้ระบบของเราเป็นไปตามหลักการของ Clean Architecture อย่างแท้จริง

Exit mobile version