Как называется этот антипаттерн?

Допустим, у меня есть функция с именем send_welcome_email() и класс с именем User (реализованный на Python, но, надеюсь, простой для понимания разработчиками, не использующими Python):

class User:
    email = TextField()
    first_name = TextField()
    last_name = TextField()


def send_welcome_email(user):
    msg = EmailMessage(recipient=user.email)
    msg.send()

В этом случае было бы лучше определить интерфейс функции как:

def send_welcome_email(email)

так что функция не связана с классом User.

Я знаю, что это известный анти-шаблон, но я не могу его найти. Кто-нибудь знает, как это называется?


person aco    schedule 17.05.2016    source источник
comment
Я разместил это в комментарии ниже, но думаю, что это заслуживает последующего обсуждения. Скажем, в send_welcome_email() требуется еще 3-4 свойства из класса User и допустим, что User имеет 10 свойств. В какой момент можно передать весь объект?   -  person Glide    schedule 20.05.2016


Ответы (4)


Я не думаю, что у антишаблона есть название, но правило, которое он нарушает, называется Закон Деметры.

LoD можно рассматривать как принцип, предполагающий «наименьшее структурное знание» (то, что его создатель называет «структурно-застенчивым программированием»). Идея состоит в том, чтобы предположить знание внутренней структуры любого объекта, кроме вашего собственного непосредственного «я».

Я слышал, как это описывалось: в магазине, когда вы платите кассиру, вы достаете свою кредитную карту из своего кошелька и отдаете ему, а не передаете кошелек и позволяете им рыться в нем. Ваш пример показывает подход к поиску; функция получает объект User и должна знать, как получить доступ к свойству электронной почты, о чем она не должна знать.

person Nathan Hughes    schedule 17.05.2016
comment
Допустим, в the send_welcome_email() требуется еще 3-4 свойства из класса User, а User имеет 10 свойств. В какой момент можно передать весь объект? - person Glide; 20.05.2016
comment
@ nathan-hughes - Я думаю, что Закон Деметры довольно близок. Аналогия мне тоже нравится! - person aco; 20.05.2016
comment
@Glide - Хороший вопрос. Возможно, это лучше описать как запах кода, чем как антишаблон. - person aco; 20.05.2016
comment
@aco: я думаю, это интересно, думаю, как решить эту проблему в ответе. - person Nathan Hughes; 20.05.2016

Функция имеет оттенок запаха кода Feature Envy. («Запахи кода» — это антипаттерны, описанные Фаулером и Беком в главе книги по рефакторингу, назван до того, как слово «антипаттерн» стало широко использоваться.) Feature Envy — это когда один модуль связан с другим модулем, вызывая слишком много методов другого модуля. В данном случае одного слишком много.

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

Это действительно напоминает один из Закон Деметры, руководство, которое уменьшает связанность, но применимо особенно для вызывающего объекта, вызывающего метод в результате вызова другого метода, чего здесь не происходит.

person Dave Schweisguth    schedule 17.05.2016

Разве вся цель send_welcome_email не состоит в том, чтобы создать электронное письмо для конкретной цели приветствия пользователя (т.е. нужна информация о пользователе, такая как имя, имя пользователя, адрес электронной почты)?

Ваш вариант не делайте этого.

Метод, вероятно, должен быть не в пользовательском классе, а что-то вроде UserEmailSender или подобного.

Поэтому мой ответ - нет: это не похоже на антишаблон.

person jgauffin    schedule 17.05.2016
comment
Нет, send_welcome_email() нужен только адрес электронной почты. Вызывающий объект не должен создавать объект User, чтобы вызвать его — это излишне связало бы эту функцию с классом User. - person aco; 17.05.2016
comment
Приветственные письма обычно содержат имя "Hi {FirstName} {LastName}" и имя пользователя: "To login, use your username: {Username}". поэтому требуется информация о пользователе. Но поскольку я не знаю, как выглядит ваша фактическая реализация, в вашем конкретном случае трудно сказать. - person jgauffin; 17.05.2016
comment
Я должен уточнить, что send_welcome_email() не является методом User, это совершенно отдельная функция. Эта функция использует только адрес электронной почты. Он создает экземпляр объекта EmailMessage, но передает ему только адрес электронной почты, а не имя и фамилию. - person aco; 17.05.2016
comment
Если он использует только электронную почту, тогда ему не требуется весь пользовательский объект. - person jgauffin; 17.05.2016

Похоже на анемическую модель домена.

person Oliver    schedule 17.05.2016
comment
Я не думаю, что @aco имеет в виду это. Это анемичная доменная модель, но я думаю, дело было в том, что send_welcome_email нужна только электронная почта, но в первом случае передавался весь пользователь. - person Aidan Kane; 17.05.2016
comment
Спасибо за разъяснение :-) - person Oliver; 17.05.2016