go - 在DDD(纯净/六角形)架构中处理数据库连接和Env配置

标签 go database-design architecture domain-driven-design

当我掌握了总体思路时,我很难看到管理配置环境和管理数据库连接的最佳实践。

含义:

  • 如果我有存储库(例如,对于PostgreSQL),是否应该将NewRepository函数传递给数据库配置?会不会以某种方式对体系结构原理(维护,可测试性等)产生不利影响?
  • 我们如何处理诸如db.Close()之类的事情?

    我的意思是,我们显然希望它与作用域主函数有关,因此将代码移到存储库“类”中是有问题的(除非有使用Context的方法?)

    另一方面,在主作用域中调用NewRepository,然后让db处理它外部的连接感觉有点奇怪。

    我发现的大多数示例都使用了main函数,因此很容易。问题是,在采用DDD(纯净/六边形)体系结构时您如何正确处理?特别是这样,所有部件都可以“插入”,而不必更改“周围”的代码。

  • 这是我放在一起的一个示例,这里是否违反了ddd模式的某些原则?还是实际上这些事情是如何完成的?

    1.我不应该在存储库本身内部处理defer db.Close()吗?也许有了上下文,我可以相对于主要功能范围推迟它,但可以在存储库本身内部进行?

    2.我是否应该将配置真正传递到NewRepository中?

    pkg / main.go:
    func main() {
    
        // get configuration stucts via .env file
        configuration, err := config.NewConfig()
        if err != nil {
            panic(err)
        }
    
        postgresRepo, err := postgres.NewRepository(configuration.Database)
    
        defer postgresRepo.DB.Close()
    
    
        myService := autocomplete.NewService(postgresRepo)
    
        handler := rest.NewHandler(myService)
    
        ...
        ...
        ...
    
    }
    

    pkg / config / config.go:
    // Config is a struct that contains configuration variables
    type Config struct {
        Environment string
        Port        string
        Database    *Database
    }
    
    // Database is a struct that contains DB's configuration variables
    type Database struct {
        Host     string
        Port     string
        User     string
        DB       string
        Password string
    }
    
    // NewConfig creates a new Config struct
    func NewConfig() (*Config, error) {
        env.CheckDotEnv()
        port := env.MustGet("PORT")
        // set default PORT if missing
        if port == "" {
            port = "3000"
        }
        return &Config{
            Environment: env.MustGet("ENV"),
            Port:        port,
            Database: &Database{
                Host:     env.MustGet("DATABASE_HOST"),
                Port:     env.MustGet("DATABASE_PORT"),
                User:     env.MustGet("DATABASE_USER"),
                DB:       env.MustGet("DATABASE_DB"),
                Password: env.MustGet("DATABASE_PASSWORD"),
            },
        }, nil
    }
    

    最佳答案

    与其将数据库配置传递到存储库中,不如尝试传递数据库连接。例如:

    func main() {
        db, err := sql.Open("postgres", "...")
        if err != nil {
            log.Fatal(err)
        }
        defer db.Close()
    
        repo := postgres.NewAutocompleteRepo(db)
        svc := autocomplete.NewService(repo)
        handler := autocomplete.NewHTTPHandler(svc)
    }
    

    这将使您有责任连接到存储库外部的数据库,并使测试更加容易。

    关于go - 在DDD(纯净/六角形)架构中处理数据库连接和Env配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60479125/

    相关文章:

    postgresql - 如何在 golang 中返回 DB(数据库/sql)类型?

    sql - 确定公式字段

    architecture - 使用哪个 UML 图来表示应用程序架构?

    date - 在 Go 中解析 RFC-3339/ISO-8601 日期时间字符串

    go - 如何关闭具有多个发送者的 channel ?

    database - 是否有用于审计持久化对象的数据库设计模式?

    c - C 中静态分配数组大小的限制

    swift - 如何以面向协议(protocol)的方式创建我的游戏架构?

    java - Google Go for Java 平台?

    mysql - 如果电子邮件地址是我网页的登录名——我应该如何设计它背后的非常简单的数据库?