Обработка соединений с БД и конфигурация Env в архитектуре DDD (чистая / шестиугольная) - PullRequest
0 голосов
/ 01 марта 2020

Хотя я понял общую идею, у меня возникли проблемы с поиском наилучшей практики для управления конфигурационными envs и управления подключением к БД.

Значение:

  1. Если У меня есть хранилище (например, для PostgreSQL). Должен ли я передать функции NewRepository конфигурацию БД? Не скажется ли это как-то отрицательно на принципах архитектуры (поддержка, тестируемость и т. Д. c.)?

  2. Как мы можем обрабатывать такие вещи, как defer db.Close ()?

    Я имею в виду, что мы, очевидно, хотели бы, чтобы это было отложено по отношению к основной функции scope, поэтому проблематично c переместить этот код в «класс» репозитория (если нет способа сделать это с помощью 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
}

1 Ответ

1 голос
/ 02 марта 2020

Вместо передачи конфигурации базы данных в ваш репозиторий, попробуйте передать соединение с базой данных. Например:

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)
}

Это оставит ответственность за подключение к базе данных за пределами репозитория и упростит тестирование.

...