在Go应用程序中实现SOLID设计

时间:2017-04-24 02:42:35

标签: go solid-principles

在没有遇到循环依赖关系的情况下,建模模型(用户)和数据库的最佳方法是什么?

我有一个我试图设置的Go应用程序。进口结构令人困惑,因为它并没有干净利落地分开关注点。我想有一个数据库存储,需要访问模型的名称来迁移它们。让模型自我迁移似乎很奇怪,这似乎是模型无关紧要的问题。同时,我想为每个需要导入数据库存储的模型进行验证。让商店验证单个模型似乎更奇怪。然而,这会产生循环依赖。

结构:

models
  - user.go
config
  - store.go

store.go

...
// CreateDb - creates table
func (i *Store) CreateDb() {
    ...
    i.DB.AutoMigrate(&models.User{})
    ...
}
...

user.go

package models

type User struct {
  Email string
}

func (u *User) ValidateUser() (err []error) {
    messages := make([]error, 0)

    // Uniqueness Validations
    email := ""

    email = config.Database.DB.Where("email LIKE ?", u.Email).First(&User)
    if email != "" {
        messages = append(messages, errors.New("Email has to be unique"))

    }

    return messages
}

我已经尝试将它们放入第三个程序包但由于它们都需要相同的依赖项 - 存储而失败。我也尝试将它们全部放入我认为有效的相同包装中,但这似乎会破坏所有结构和关注点。

么?

我的解决方案

我最终将数据库指针解耦为一个单独的包,然后将迁移作为引导过程的一部分。然而,我保留了与模型包一致的验证。

1 个答案:

答案 0 :(得分:1)

我不是Go人,但因为这是一个设计问题,所以没关系。不允许重复的电子邮件是业务要求。此外,根据业务需求,在验证之前/之后但在访问数据库存储之前,您可能需要执行其他操作。

我会将验证放在另一个包中,该包将充当业务逻辑层并引用模型和存储包。我将保持模型清洁,就像我们分别在C#,Java中使用POCO,POJO一样。不知道在Go上下文中将它们称为什么。 POGO专为Groovy保留:)。

请参阅下面的伪代码:

// business
function AddUser(email) {
    User user;
    // validate
    user = store.GetUserByEmail(email);
    if (user) {
        // shout
    }
    else {
        user = new User { Email = email }; // basically initialize user instance to store
        store.InsertUser(user); 
    }
}

这是我谈到的基本内容。您可以定义业务包用于与存储进行通信的接口,然后是依赖注入,而不是。