Golang и DDD доменное моделирование - PullRequest
0 голосов
/ 25 февраля 2019

В последнее время я изучаю дизайн, управляемый предметной областью, и должен сказать, что этот тип архитектурного дизайна вызывает у меня что-то.Когда я пытаюсь применить его концепции к своему проекту Go, я сталкиваюсь с некоторыми препятствиями.Ниже приведены некоторые примеры методов, но я очень не уверен, с каким методом перейти.

Выдержка из структуры проекта:

├── api/
├── cmd/
├── internal/
|   ├── base/
|   |   ├── eid.go
|   |   ├── entity.go
|   |   └── value_object.go
|   ├── modules/
|   |   ├── realm/
|   |   |   ├── api/
|   |   |   ├── domain/
|   |   |   |   ├── realm/
|   |   |   |   |   ├── service/
|   |   |   |   |   ├── friendly_name.go
|   |   |   |   |   ├── realm.go
|   |   |   |   |   └── realm_test.go
|   |   |   |   └── other_subdomain/
|   |   |   └── repository/
|   |   |       ├── inmem/
|   |   |       └── postgres/

Общая для всех методов:

package realm // import "git.int.xxxx.no/go/xxxx/internal/modules/realm/domain/realm"

// base contains common elements used by all modules
import "git.int.xxxx.no/go/xxxx/internal/base"

Метод # 1:

type Realm struct {
   base.Entity

   FriendlyName FriendlyName
}

type CreateRealmParams struct {
    FriendlyName string
}

func CreateRealm(id base.EID, params *CreateRealmParams) (*Realm, error) {
   var err error
   var r = new(Realm)

   r.Entity = base.NewEntity(id)
   r.FriendlyName, err = NewFriendlyName(params.FriendlyName)

   return r, err
}

type FriendlyName struct {
    value string
}

var ErrInvalidFriendlyName = errors.New("invalid friendly name")

func (n FriendlyName) String() string { return n.value }

func NewFriendlyName(input string) (FriendlyName, error) {
    if input == "" {
        return ErrInvalidFriendlyName
    }
    // perhaps some regexp rule here...

    return FriendlyName{value: input}, nil
}

С этим методом я думаю, что в долгосрочной перспективе будет много повторяющегося кода, но по крайней мере объект-значение FriendlyName является неизменным согласно требованиям DDD и открывается длядополнительные методы должны быть присоединены.

Метод # 2:

type Realm struct {
    base.Entity

    FriendlyName string
}

type CreateRealmParams struct {
    FriendlyName string
}

func CreateRealm(id base.EID, params *CreateRealmParams) (*Realm, error) {
    var err error

    if err = validateFriendlyName(params.FriendlyName); err != nil {
        return nil, err
    }

    entity := base.NewEntity(id)

    return &Realm{
        Entity: entity,
        FriendlyName: params.FriendlyName,
    }, nil
}

Это, наверное, самый распространенный пример, который я встречал там, за исключением проверки, которой не хватает во многих примерах..

Метод № 3:

type Realm struct {
    base.Entity

    friendlyName string
}

type CreateRealmParams struct {
    FriendlyName string
}

func CreateRealm(id base.EID, params *CreateRealmParams) (*Realm, error) {
    var err error

    if err = validateFriendlyName(friendlyName); err != nil {
        return nil, err
    }

    entity := base.NewEntity(id)

    return &Realm{
        Entity: entity,
        friendlyName: friendlyName,
    }, nil
}

func (r *Realm) FriendlyName() string { return r.friendlyName }
func (r *Realm) SetFriendlyName(input string) error {
    if err := validateFriendlyName(input); err != nil {
        return err
    }
    r.friendlyName = input
    return nil
}

Здесь понятный тип имени - это просто строка, но неизменяемая.Эта структура напоминает мне код Java ... При поиске области должен ли уровень хранилища использовать методы установки из модели предметной области для построения агрегата области?Я пытался с реализацией DTO, помещенной в тот же пакет (dto_sql.go), который кодировал / декодировал в / из агрегата области, но это было неправильно, если поместить эту проблему в пакет домена.

Если высталкиваются с теми же проблемами, что и я, знают о любом другом методе или есть что-то, на что можно указать, мне будет очень интересно услышать от вас!

...