Паттерн Configurable Object
В комментариях к предыдущему посту многие написали, что предпочитают Configurable Object вместо Functional Options. Это тоже важный подход, поэтому процитирую комментарий комментарий моего бывшего коллеги Антона Зиновьева (и прокомментирую его ниже):
В случае если параметров действительно много, то становится не очень красиво, т.к. надо всегда писать имя пакета, которое далеко не всегда короткое.
Для таких случаев мне нравится использовать Configurable Object, методы конфигураторы которого чейнятся. Получится что-то вроде.
foo.Bar(uid, msg,
foo.BarOpt{}.
WithEmail(email).
WithPriority(foo.PriorityHight))
Сохраняется преимущество функциональных аргументов (их главный плюс - внутри может быть зашита дополнительная логика) и при этом несколько чище, чем просто функциональные аргументы.
Нет замусоривания пакета функциями With* - все функции пришиты к соответствующим конфигам.
——————
Честно говоря, я не вижу причин для дискуссии - оба подхода я очень люблю и регулярно использую в работе. Правда, Configurable Object чаще использую немного для другого - для конфигурирования объекта, которым собираюсь непосредственно пользоваться, а не для формирования конфигурационного объекта, который я собираюсь куда-то передать, но идея мне нравится.
Однако, в большинстве случаев проще просто структуру передать, т.к. внутрення логика при назначении опций требуется чуть чаще, чем никогда, по моему опыту.
Чаще всего я конфигурирую таким образом логгер, и это действительно чертовски удобно:
func (s *MyService) SomeMethod(userID int) {
const op = “MyService.SomeMethod”
log := s.logger.Named(op).WithString(“user_id”, userID)
// …
}
——————
Кстати, по поводу: «надо всегда писать имя пакета, которое далеко не всегда короткое …» (c) Антон З.
Но ведь для этого существуют алиасы при импорте пакетов! 🤓
В таких случаях они очень выручают как раз.
Расскажите в комментариях, что думаете об этом подходе и о его сравнении с OptFunc
#pattern
В комментариях к предыдущему посту многие написали, что предпочитают Configurable Object вместо Functional Options. Это тоже важный подход, поэтому процитирую комментарий комментарий моего бывшего коллеги Антона Зиновьева (и прокомментирую его ниже):
В случае если параметров действительно много, то становится не очень красиво, т.к. надо всегда писать имя пакета, которое далеко не всегда короткое.
Для таких случаев мне нравится использовать Configurable Object, методы конфигураторы которого чейнятся. Получится что-то вроде.
foo.Bar(uid, msg,
foo.BarOpt{}.
WithEmail(email).
WithPriority(foo.PriorityHight))
Сохраняется преимущество функциональных аргументов (их главный плюс - внутри может быть зашита дополнительная логика) и при этом несколько чище, чем просто функциональные аргументы.
Нет замусоривания пакета функциями With* - все функции пришиты к соответствующим конфигам.
——————
Честно говоря, я не вижу причин для дискуссии - оба подхода я очень люблю и регулярно использую в работе. Правда, Configurable Object чаще использую немного для другого - для конфигурирования объекта, которым собираюсь непосредственно пользоваться, а не для формирования конфигурационного объекта, который я собираюсь куда-то передать, но идея мне нравится.
Однако, в большинстве случаев проще просто структуру передать, т.к. внутрення логика при назначении опций требуется чуть чаще, чем никогда, по моему опыту.
Чаще всего я конфигурирую таким образом логгер, и это действительно чертовски удобно:
func (s *MyService) SomeMethod(userID int) {
const op = “MyService.SomeMethod”
log := s.logger.Named(op).WithString(“user_id”, userID)
// …
}
——————
Кстати, по поводу: «надо всегда писать имя пакета, которое далеко не всегда короткое …» (c) Антон З.
Но ведь для этого существуют алиасы при импорте пакетов! 🤓
В таких случаях они очень выручают как раз.
Расскажите в комментариях, что думаете об этом подходе и о его сравнении с OptFunc
#pattern