我正在构建一个go web服务并试图遵循"清洁代码"或"域驱动设计"原则。我的精简文件夹结构如下所示:
- api
- postgre
employee_service.go
employee.go
基本布局是我的root(api)文件夹是我的所有域代码。并且所有软件包都是适配器,以使我的域工作,但如果需要,很容易更换。我的employee.go
文件可能如下所示:
type EmployeeService interface{
CreateEmployee(e *Employee) error
}
type Employee struct {
ID string
Name string
}
我遇到的问题是在我的应用上放置某些东西,因为他们觉得他们是我的域逻辑的一部分;但是域逻辑不应该有任何外部依赖,所以它让我陷入困境。以下是我要创建新员工的示例:
postgre/employee_service.go:
type EmployeeService struct {
DB *pg.DB
}
func (s *EmployeeService) CreateEmployee(e *api.Employee) error {
e.ID = uuid.NewV4().String()
// insert to db
}
现在你可以想象Employee
结构域有更多的字段,而不仅仅是我需要在将它插入数据库之前设置的ID或名称。所以我的想法是在我的应用程序的根目录中为User
结构添加一个方法,如下所示:
/employee.go
func (e *Employee) New() {
e.ID = uuid.NewV4()
// add any other fields I need
}
postgre用户服务看起来像这样:
postgre/employee_service.go:
func (s *EmployeeService) CreateEmployee(e *api.Employee) error {
e.New()
// insert to db
}
现在问题是我的应用的域依赖于uuid
包。在我看来这很好,因为如果我要更换postgre的mysql或mongo或任何其他DB New()
方法不会改变。另外一个"复杂"例如密码哈希,无论数据库是什么,我的密码哈希都将生成相同,所以我相信这属于我的域逻辑所在的根文件夹。再次哈希密码我会crypto/bcrypt
依赖性破坏DDD规则,你的域应该没有外部依赖。