【问题标题】:What is this anti-pattern called?这种反模式叫什么?
【发布时间】:2016-09-13 03:54:43
【问题描述】:

假设我有一个名为 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类耦合。

我知道这是一个已知的反模式,但我找不到它。谁知道它叫什么?

【问题讨论】:

  • 我在下面的评论中发布了这个,但认为它值得后续讨论。假设在 send_welcome_email() 中,它需要来自 User 类的 3-4 个属性,并且说 User 有 10 个属性。什么时候可以传递整个对象?

标签: design-patterns language-agnostic terminology anti-patterns


【解决方案1】:

我认为反模式没有名称,但违反的规则称为Law of Demeter。

LoD 可以被视为假设“最少结构知识”的原则(它的创建者称之为“结构害羞编程”)。这个想法是假设除了你自己的直接自我之外,不知道任何对象的内部结构。

我听到的描述是这样的:在商店里,如果您向收银员付款,您会从钱包中取出信用卡并将其交给他们,而不是交出钱包让他们翻找。您的示例显示了翻找方法;该函数获取 User 对象,并且它必须知道如何访问 email 属性,这是它不应该知道的。

【讨论】:

  • 假设在 the send_welcome_email() 中它需要来自 User 类的 3-4 个属性,并且说 User 有 10 个属性。什么时候可以传递整个对象?
  • @nathan-hughes - 我认为得墨忒耳法则非常接近。我也喜欢这个比喻!
  • @Glide - 好问题。也许将其描述为代码异味而不是反模式更好。
  • @aco:我认为这很有趣,正在考虑如何在答案中解决这个问题。
【解决方案2】:

该功能有一点the Feature Envy code smell。 (“代码异味”是反模式,Fowler 和 Beck 在 the Refactoring book 的一章中有记载,在“反模式”这个词被广泛使用之前命名。)特性嫉妒是指一个模块通过调用太多的另一个模块的方法。在这种情况下,一个太多了。

通常的解决方法是将一个方法提取到另一个模块上,但这不适用于这里,因为只有一个臭方法调用。只要调用者可以与User 类进行耦合,要求函数的调用者调用该方法的修复程序就会起作用。

这确实提醒了 Law of Demeter 中的一个,这是一个减少耦合的准则,但它最特别适用于调用者在调用另一个方法的结果上调用一个方法,这在此处不会发生。

【讨论】:

    【解决方案3】:

    send_welcome_email 的全部目的不是为了欢迎用户的特定目的而生成电子邮件(即需要有关用户的信息,例如姓名、用户名、电子邮件地址)吗?

    您的替代方案不这样做。

    该方法可能不应该在用户类中,而应该是 UserEmailSender 或类似的。

    因此我的回答是否定的:它看起来不像是反模式。

    【讨论】:

    • 不,send_welcome_email() 只需要一个电子邮件地址。调用者不必为了调用它而构造一个 User 对象 - 这会不必要地将该函数耦合到 User 类。
    • 欢迎电子邮件通常包含姓名"Hi {FirstName} {LastName}" 和用户名:"To login, use your username: {Username}"。因此需要用户信息。但由于我不知道您的实际实现情况如何,因此在您的具体情况下很难判断。
    • 我应该澄清send_welcome_email()不是User的方法,它是一个完全独立的函数。此功能仅使用电子邮件地址。它正在实例化一个EmailMessage 对象,但只将电子邮件地址传递给它,而不是名字和姓氏。
    • 如果它只使用电子邮件,那么它不应该需要整个用户对象。
    【解决方案4】:

    听起来像Anemic Domain Model。

    【讨论】:

    • 我不认为这就是@aco 所指的。这是一个贫乏的域模型,但我认为重点是 send_welcome_email 只需要电子邮件,但在第一种情况下,整个用户都被传入了。
    • 感谢您的澄清 :-)
    猜你喜欢
    • 1970-01-01
    • 2016-02-06
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多