【问题标题】:"messy-polymorphism" anti-pattern“混乱多态”反模式
【发布时间】:2009-04-03 00:09:53
【问题描述】:

在相当大的 Ruby 应用程序中,我们会遇到这样一种情况,即给定对象由以下几项标识:名称和 ID。这些值类型中的每一个都有不同的用途,因此并不完全等效(id 和 name 在不同的地方保留)。因此,我们最终会在应用程序中传递各种值(id、名称和对象)。这种情况至少在某种程度上似乎是一个问题,因为我们已经被错误所困扰,这些错误涉及不清楚应该将什么类型传递给给定函数。我实际上记得这些年来在许多应用程序中看到过类似的问题代码,尽管我再一次没有给它一个具体的名字。

Ruby 作为一种无类型语言,不像 C++ 那样允许经典的基于类型的多态函数。作为一种变通方法,一位同事经常使用这种代码:

  def initialize starting_value
    if starting_post.kindof? Foo
      @starting_id = get_id_from_foo starting_value
    elsif starting_post.kindof? Bar
      @starting_id = get_id_from_bar starting_value
    else
      raise "illegal type"
    end
  end

这些代码围绕我们的代码库(不仅仅是初始化程序)的扩散导致了我所说的“混乱多态性”。它通常有效,但有时会产生非常令人费解的情况。

我对此有三个问题。

  • 是否有正式名称作为 反模式? “混乱的接口?”,“混乱的多态性?”还是别的什么?
  • 人们认为这有多糟糕?
  • 是否有系统的重构方式 这?我们面临的挑战 我们创建的许多测试都使用它的普通重构 松散类型,因此我们必须同时更改 测试和实现 同时,不会有普通测试的脚手架效应 重构。我认为实际上可以“加强”这种松散的多态性, 并将代码抽象为一个函数,而不是立即将其撕掉。但是会 这是个好主意吗?

【问题讨论】:

    标签: ruby refactoring tdd polymorphism anti-patterns


    【解决方案1】:

    您不能定义某种 get_id 方法,以便 id 返回自身,对象返回 id,并且名称执行获取 id 所需的任何操作吗?然后,您始终可以将任何您知道将是三者之一的东西规范化。如果需要,也可以使用 get_name 和 get_object 方法。

    也就是说,您已经定义了一个隐式 ThingWhatHasAnID 接口,并将其设为函数参数的鸭子类型。

    除非我遗漏了什么,否则我会将这种反模式称为“错过了创建抽象的机会”。

    【讨论】:

      【解决方案2】:

      几乎任何时候你发现自己切换到一个对象的类,它的行为应该是对象本身的一个方法的线索。消息调度多态的基于接收者。在这种情况下,它应该是这样的:

      def initialize starting_value
        @starting_id = starting_value.id
      end
      

      定义id 来执行各种get_id_from_* 方法用来执行的操作。非法类型案例已经出现,因为你会得到 NoMethodError。

      至于叫什么,我称之为“面向对象语言的过程编程”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-09
        • 1970-01-01
        • 1970-01-01
        • 2010-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-30
        相关资源
        最近更新 更多