2017-02-18 7 views
2

Стоит ли групповые методы в структурах: Например:Golang код структурирования

type UserManager struct { 
    DB *sql.DB 
} 

func (m UserManager) Insert (u User) error {...} 
func (m UserManager) Delete (u User) error {...} 
... 

Или это проще поддержка только отдельные функции.

func InsertUser (u User, db *sql.DB) error {...} 

В то время как второй подход выглядит проще, в будущем, таким образом, может быть много функций в пакете. Должен ли я делать отдельный пакет для каждого агрегата домена? В примерах, которые я видел до сих пор, есть только пакет model. Я работаю в основном с языками OO, поэтому вам нужно посоветоваться с лучшими практиками.

+0

Предлагаю перейти с первого подхода. Это делает кодовую базу более структурированной и более читаемой. Создавая экземпляр или UserManager, все приложение, которое может быть сделано на нем, будет очень четким при кодировании. –

ответ

1

Ваше второе предложение - нехороший код! Зачем? Потому что в лучшем случае функция должна принимать интерфейсы в качестве входных данных.

Так InsertUser функция должна выглядеть примерно так и было бы объединить ваш первый со своим вторым предложением:

type Inserter interface { 
    Insert(User)error 
} 
func InsertUser(i Inserter) error {...} 

В этом случае тестирование вашей функции легко, потому что вы можете легко дразнить вставки.

+0

Мне нравится, что этот ответ делает то же самое, что я и пытался, но с совершенно другого ракурса. Я думаю, что это действительно говорит о том, насколько сильно интерфейс на основе интерфейса может сходиться, и я думаю, что это настоящая красота Go – nothingmuch

1

Либо, или ни - это на самом деле не имеет значения, на мой взгляд, потому что идиоматическое подход должен был бы организовать эти понятия с помощью интерфейса:

package user 

type User ... 

type Inserter interface { Insert(User) error } 
type Deleter interface { Delete(User) error } 
type Manager interface { Inserter, Deleter } // bloated interface 

User в этом случае, вероятно, является конкретный тип строки, как в ваш пример, но можно было бы сделать так, чтобы он тоже превратился в интерфейс, который не упоминает эти типы.

Если вы пишете функции, которые ссылаются на эти интерфейсы, вы можете быстро склеить их, используя embedding & promoted fields.

В вашем случае это очевидно, что прилипание к первому стилю реализации гораздо проще:

type userManager struct { ... } 
func (userManager) Insert(u User) error { ... } 
func (userManager) Delete(u User) error { ... } 

userManager является частным типа, поэтому она может быть изменена без заботы, до тех пор, как он держит удовлетворяющий открытые интерфейсы ,

Сохранение интерфейсов, отделенных от реализации, значительно упрощает их сужение, поэтому вместо того, чтобы иметь «пользовательский менеджер» или что-то еще, вы можете узнать, какие интерфейсы вам действительно нужны для задач. Кстати, этот подход имеет приятное свойство, которое хорошо сочетается с object capability model, что упрощает такие функции, как управление доступом на основе ролей.

 Смежные вопросы

  • Нет связанных вопросов^_^