Go Programming – Hexagonal Architecture: คู่มือฉบับสมบูรณ์

Go Programming – Hexagonal Architecture

Hexagonal Architecture หรือที่รู้จักกันในชื่อ Ports and Adapters Architecture เป็นแนวทางในการออกแบบซอฟต์แวร์ที่เน้นการแยกส่วนประกอบ (separation of concerns) เพื่อให้โค้ดมีความยืดหยุ่น ทดสอบง่าย และปรับเปลี่ยนได้ง่ายขึ้น ในบทความนี้ เราจะมาเจาะลึกถึงหลักการของ Hexagonal Architecture และวิธีการนำไปประยุกต์ใช้ในการเขียนโปรแกรมด้วยภาษา Go (Go Programming) พร้อมทั้งยกตัวอย่างการใช้งานจริง

Introduction to Hexagonal Architecture

Hexagonal Architecture คือสถาปัตยกรรมซอฟต์แวร์ที่ออกแบบมาเพื่อลดการพึ่งพากันระหว่างส่วนประกอบต่างๆ ของระบบ โดยมีเป้าหมายหลักคือการทำให้โค้ดมีความยืดหยุ่นต่อการเปลี่ยนแปลงของเทคโนโลยีภายนอก เช่น ฐานข้อมูล หรือ API ต่างๆ

What is Hexagonal Architecture?

Hexagonal Architecture มองว่าระบบซอฟต์แวร์ประกอบด้วย “core” หรือแกนหลัก ซึ่งเป็นที่อยู่ของ business logic และ “ports and adapters” ที่ทำหน้าที่เป็นตัวเชื่อมต่อกับโลกภายนอก โดย ports จะกำหนด interface หรือข้อกำหนดในการสื่อสาร ส่วน adapters จะเป็นตัวแปลงข้อมูลให้เข้ากับ interface ที่กำหนด

Why use Hexagonal Architecture?

การใช้ Hexagonal Architecture ช่วยให้โค้ดมีความยืดหยุ่นมากขึ้น เนื่องจาก business logic ไม่จำเป็นต้องขึ้นอยู่กับเทคโนโลยีภายนอกโดยตรง นอกจากนี้ยังช่วยให้การทดสอบง่ายขึ้น เพราะเราสามารถสร้าง mock adapters เพื่อจำลองการทำงานของระบบภายนอกได้

Benefits of using Hexagonal Architecture

ข้อดีหลักๆ ของ Hexagonal Architecture ได้แก่ testability, maintainability และ flexibility ช่วยให้การพัฒนาซอฟต์แวร์เป็นไปอย่างมีประสิทธิภาพและยั่งยืน

Components of Hexagonal Architecture

Hexagonal Architecture ประกอบด้วยส่วนประกอบหลักๆ ดังนี้

Ports and Adapters

Ports คือ interface ที่กำหนดวิธีการสื่อสารกับระบบภายนอก เช่น ฐานข้อมูล หรือ API ต่างๆ Adapters ทำหน้าที่เป็นตัวกลางในการแปลงข้อมูลให้เข้ากับ ports โดยมี adapters หลายประเภท เช่น database adapters, API adapters และ test adapters

Business Logic Layer

Business Logic Layer คือส่วนที่เก็บ business rules และ logic ทั้งหมดของแอปพลิเคชัน ส่วนนี้ไม่ควรขึ้นอยู่กับเทคโนโลยีภายนอกใดๆ

External Layer

External Layer คือส่วนที่ติดต่อกับระบบภายนอก เช่น ฐานข้อมูล, API, หรือ UI โดยใช้ adapters ในการสื่อสาร

Implementing Hexagonal Architecture in Go

การนำ Hexagonal Architecture มาใช้ใน Go Programming ต้องอาศัยการออกแบบโครงสร้างโปรเจกต์ที่เหมาะสม และการเขียนโค้ดที่สอดคล้องกับหลักการของ ports and adapters

Project Structure

โครงสร้างโปรเจกต์ทั่วไปสำหรับ Hexagonal Architecture ใน Go อาจมีลักษณะดังนี้

  • /cmd: โฟลเดอร์สำหรับ main package
  • /internal: โฟลเดอร์สำหรับโค้ดภายใน
  • /internal/core: โฟลเดอร์สำหรับ business logic
  • /internal/ports: โฟลเดอร์สำหรับ ports (interfaces)
  • /internal/adapters: โฟลเดอร์สำหรับ adapters
  • /internal/adapters/database: โฟลเดอร์สำหรับ database adapters
  • /internal/adapters/api: โฟลเดอร์สำหรับ API adapters
  • /internal/services: โฟลเดอร์สำหรับ service layer
  • /internal/handlers: โฟลเดอร์สำหรับ handler layer

Code Walkthrough

เราจะมาดูตัวอย่างการเขียนโค้ดโดยใช้ Hexagonal Architecture ใน Go Programming

Project Structure and Code Walkthrough

มาดูโครงสร้างโปรเจกต์และตัวอย่างโค้ดในแต่ละเลเยอร์

Repository Layer

Repository Layer ทำหน้าที่เป็น interface สำหรับการเข้าถึงข้อมูล โดยทั่วไปจะมี interface ที่กำหนดวิธีการเข้าถึงข้อมูล เช่น การสร้าง, อ่าน, อัปเดต, และลบข้อมูล

ตัวอย่าง: internal/ports/customer_repository.go


type CustomerRepository interface {
    GetCustomer(id string) (*Customer, error)
    CreateCustomer(customer *Customer) error
}

Service Layer

Service Layer ทำหน้าที่เป็นตัวกลางในการจัดการ business logic โดยจะเรียกใช้ repository layer เพื่อเข้าถึงข้อมูล

ตัวอย่าง: internal/services/customer_service.go


type CustomerService struct {
    repo CustomerRepository
}

func (s *CustomerService) GetCustomer(id string) (*Customer, error) {
    return s.repo.GetCustomer(id)
}

Handler Layer

Handler Layer ทำหน้าที่รับ request จากภายนอก (เช่น HTTP request) และเรียกใช้ service layer เพื่อประมวลผล

ตัวอย่าง: internal/handlers/customer_handler.go


type CustomerHandler struct {
    service CustomerService
}

func (h *CustomerHandler) GetCustomer(w http.ResponseWriter, r *http.Request) {
    id := r.URL.Query().Get("id")
    customer, err := h.service.GetCustomer(id)
    // ... handle error and return response
}

Testing and Mocking

การทดสอบเป็นส่วนสำคัญในการพัฒนาซอฟต์แวร์ Hexagonal Architecture ช่วยให้การทดสอบง่ายขึ้น

Mocking the Repository

เราสามารถสร้าง mock repository เพื่อจำลองการทำงานของ repository layer ได้ ทำให้เราสามารถทดสอบ service layer โดยไม่ต้องพึ่งพาฐานข้อมูลจริง

ตัวอย่าง: internal/adapters/database/customer_repository_test.go


type MockCustomerRepository struct {
    GetCustomerFunc func(id string) (*Customer, error)
}

func (m *MockCustomerRepository) GetCustomer(id string) (*Customer, error) {
    return m.GetCustomerFunc(id)
}

Testing the Service

เราสามารถทดสอบ service layer โดยใช้ mock repository เพื่อตรวจสอบว่า service layer ทำงานถูกต้องหรือไม่

ตัวอย่าง: internal/services/customer_service_test.go


func TestCustomerService_GetCustomer(t *testing.T) {
    // ... setup mock repository
    // ... call service method
    // ... assert results
}

Testing the Handler

เราสามารถทดสอบ handler layer โดยใช้ mock service เพื่อตรวจสอบว่า handler layer ทำงานถูกต้องหรือไม่

ตัวอย่าง: internal/handlers/customer_handler_test.go


func TestCustomerHandler_GetCustomer(t *testing.T) {
    // ... setup mock service
    // ... create HTTP request
    // ... call handler method
    // ... assert response
}

Benefits of Hexagonal Architecture

Hexagonal Architecture มีข้อดีหลายประการที่ช่วยให้การพัฒนาซอฟต์แวร์มีประสิทธิภาพมากขึ้น

Testability

การแยกส่วนประกอบทำให้ง่ายต่อการเขียน unit tests และ integration tests

Maintainability

การเปลี่ยนแปลงในส่วนใดส่วนหนึ่งของระบบจะไม่ส่งผลกระทบต่อส่วนอื่นๆ

Flexibility

สามารถเปลี่ยนเทคโนโลยีภายนอกได้ง่าย เช่น เปลี่ยนฐานข้อมูล หรือ API โดยไม่ส่งผลกระทบต่อ business logic


💬 ปรึกษาการเงินฟรีกับผู้เชี่ยวชาญ คลิกเพื่อแอดไลน์


👉 แอดไลน์เพื่อปรึกษาฟรี


หรือสแกน QR เพื่อแอด

QR Code Line