สมอง SML

คลังความรู้ / หลังบ้าน Go

#backend#go#architecture#di

สถาปัตยกรรม Hexagonal และ composition root

backend ของ SML Ai Account เป็น Go module github.com/smlsoft/smlaiaccountapi (go 1.26.0, go.mod:1,3) จัดชั้นแบบ Hexagonal: domain (กฎล้วน) → application (use case + port) → adapter (inbound = HTTP, outbound = DB/ไฟล์/MinIO) โดย internal/di/container.go เป็นจุดเดียวที่ประกอบ (wire) ทุกชั้นเข้าด้วยกัน.

ทำงานอย่างไร

  1. cmd/api/main.go เรียก config.Load() → logger.New() → di.Build(cfg, log) → httpserver.New(port, container.Handler, log) (วงจรชีวิตเซอร์วิสและการรัน binary เดียวหลาย OS (Service lifecycle)).
  2. di.Build (internal/di/container.go:62) ประกอบตามลำดับ:
  3. Container{Config, Logger, Pools, Handler} (:54-59); Close() เรียก Pools.CloseAll() (:184-186) ตอนปิดเซอร์วิส.

กติการะหว่างชั้น (ตามคำอธิบายใน README)

  • domain: Go ล้วน ไม่ import SQL/HTTP/framework.
  • application: import domain เท่านั้น เป็นที่อยู่ของ port (port.go) และ use case (service.go).
  • adapter/inbound/*: เรียก inbound port; adapter/outbound/*: implement outbound port ด้วย pgx/ไฟล์/MinIO.
  • platform/*: ของข้ามชั้น (config, logger, db pool, security, apperr) (README.md:47-56).

โครงสร้างจริงใต้ backend/internal (ตรวจจากต้นไม้ไฟล์)

ชั้น โฟลเดอร์ที่มีจริง
domain blob, identity, query, tenant
application blob, identity, process, query, tenant
adapter/inbound/http admin, ai, autocare, blob, crm, dashboard, etax, identity, market, mcp, middleware, monitormap, ops, pos, process, procure, query, response, tenant, tms, wms + router.go
adapter/outbound blob, blobsql, crypto, dynamicsql, identity, query, tenant
platform apperr, config, db, docno, httpserver, logger, search, security, sqllit

รูปแบบซ้ำ: ทุก context ที่ต้องต่อ DB ผู้เช่ามี provider_connection_resolver.go ใน outbound (identity/query/blob) ซึ่งห่อ tenantService.GetProviderConnection เพื่อให้ application ไม่รู้จักไฟล์ config (โมเดลผู้เช่าหลายราย: Tenant, Provider, Main DB, Company (Multi-tenant model)).

จุดที่โค้ดจริงต่างจากแผนใน README

  • README (README.md:62-85) วางแผนโฟลเดอร์ adapter/inbound/consumer, outbound/postgres, storage, mqpublisher, pdf, qrcode, และ golang-migrate — ในต้นไม้จริงไม่มีโฟลเดอร์เหล่านี้ และ go.mod ไม่มี golang-migrate (ไฟล์ migration และการสร้างตารางตอนรัน (Migrations / runtime DDL)). ตาราง bounded context (README.md:90-110) ระบุหลาย context ว่า "ยังไม่เริ่ม" แต่ router มี pos/dashboard/wms ฯลฯ อยู่แล้ว — README ล้าสมัย ให้ยึดโค้ด.
  • handler ของโมดูล (wms, tms, procure, etax, market, crm, autocare, monitormap) ไม่ผ่าน repository เฉพาะของตัวเอง แต่เรียก use case ของ query/blob ผ่าน ExecInput.AllowDDL = true เพื่อสร้างตาราง/เขียนข้อมูลเอง (application/query/port.go:64, เช่น wms/handler.go:1283) และบางตัวมี EnsureSeeded ที่ di ผูกต่อกัน (container.go:120-145).
  • ADR/คำศัพท์โดเมน (Tenant, Main Database, Company, DataGroup, Access Grant, Session, Pre-auth token) นิยามไว้ที่ CONTEXT.md:7-41 (โมเดลผู้เช่าหลายราย: Tenant, Provider, Main DB, Company (Multi-tenant model)).

ที่มาในโค้ด

  • backend/go.mod:1-3 — ชื่อ module และเวอร์ชัน Go.
  • backend/internal/di/container.go:62-182 — ลำดับการ wire ทั้งหมด; :184 Close.
  • backend/README.md:28-56 — หลักการ Hexagonal และกติกา dependency.
  • backend/internal/application/query/port.go:64 — AllowDDL ที่โมดูลใช้.

ดูเพิ่ม

ภาพรวม Backend Go ของ SML Ai Account (Backend overview) · Router, middleware และแผนผัง route ทั้งหมดของ backend (chi router) · ตัวแปรสภาพแวดล้อมและการโหลด config ของ backend (Environment config) · วงจรชีวิตเซอร์วิสและการรัน binary เดียวหลาย OS (Service lifecycle) · สารบัญ ADR ของ backend (Architecture Decision Records)