1、领域驱动设计最佳实践
分层概念
在领域驱动设计中,通常将一个应用系统划分为四层架构,分别是表现层、应用层、领域层和基础设施层。
- 表现层:负责处理用户界面和用户交互,如接收用户输入,显示输出结果等。
- 应用层:负责协调应用程序的活动,如处理业务用例和业务流程等。
- 领域层:负责实现业务逻辑和业务规则,包含领域模型和领域服务等。
- 基础设施层:负责提供技术支持,如数据持久化、消息传递、日志记录等。
这四层之间有着严格的依赖关系,上层依赖于下层,而下层不依赖于上层。这样的分层架构有助于实现高内聚低耦合的设计原则。
目录架构参考
├─catalog // 商品目录子域
│ ├─application // 应用层
│ │ ├─brand
│ │ ├─category
│ │ ├─collection
│ │ └─product
│ ├─domain // 领域层
│ │ ├─brand // 商品品牌模块
│ │ ├─category // 商品类目模块
│ │ ├─collection // 商品集合模块
│ │ └─product // 商品模块
│ ├─infrastructure // 基础设施层
│ │ └─persistent // 持久化
│ │ ├─jpa
│ │ ├─mybatis
│ │ └─redis
│ └─presentation // 表现层
│ ├─graphql
│ ├─grpc
│ ├─rest
│ ├─view
│ └─websocket
└─order
├─application
│ ├─dispute
│ ├─review
│ ├─shipping
│ └─source
├─domain
│ ├─dispute
│ ├─review
│ ├─shipping
│ └─source
├─infrastructure
└─presentation [^2^][1]
表现层demo
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello, this is the presentation layer!")
})
fmt.Println("Starting server on port 8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
panic(err)
}
}
应用层demo
package main
import "fmt"
type Order struct {
ID string
}
type OrderService interface {
CreateOrder(order Order) error
}
type OrderServiceImpl struct{}
func (s *OrderServiceImpl) CreateOrder(order Order) error {
fmt.Printf("Creating order with ID: %s\n", order.ID)
return nil
}
func main() {
orderService := &OrderServiceImpl{}
order := Order{ID: "123"}
err := orderService.CreateOrder(order)
if err != nil {
panic(err)
}
}
领域层demo
package main
import (
"errors"
"fmt"
)
type Order struct {
ID string
Quantity int
}
func (o *Order) Validate() error {
if o.ID == "" {
return errors.New("order ID cannot be empty")
}
if o.Quantity <= 0 {
return errors.New("order quantity must be greater than 0")
}
return nil
}
func main() {
order := Order{ID: "123", Quantity: 2}
err := order.Validate()
if err != nil {
panic(err)
}
fmt.Println("Order is valid")
}
基础设施层demo
package main
import "fmt"
type Order struct {
ID string
}
type OrderRepository interface {
Save(order Order) error
}
type OrderRepositoryImpl struct{}
func (r *OrderRepositoryImpl) Save(order Order) error {
fmt.Printf("Saving order with ID: %s\n", order.ID)
return nil
}
func main() {
orderRepository := &OrderRepositoryImpl{}
order := Order{ID: "123"}
err := orderRepository.Save(order)
if err != nil {
panic(err)
}
}