代码之家  ›  专栏  ›  技术社区  ›  Joe Soul-bringer

“混乱多态”反模式

  •  5
  • Joe Soul-bringer  · 技术社区  · 17 年前

    在相当大的Ruby应用程序中,我们会遇到这样一种情况:给定的对象由两个东西标识:比如名称和id。这些值类型中的每一种都有不同的用途,因此并不完全相同(id和name存在于不同的位置)。因此,我们最终会在应用程序中传递各种值(ID、名称和对象)。这种情况在某种程度上似乎是一个问题,因为我们已经被一些bug所困扰,这些bug涉及到不清楚应该向给定函数传递什么类型。事实上,我记得多年来在许多应用程序中看到过类似的问题代码,尽管我再次没有给它起过具体的名字。

    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
    

    这段代码在我们的代码库(不仅仅是初始值设定项)中的扩散导致了我所谓的“混乱多态性”。它通常有效,但有时会造成非常令人费解的情况。

    关于这一点,我有三个问题。

    • 这个有正式的名字吗 反模式?“凌乱的接口?”,“凌乱的多态性?”还是其他什么?
    • 这我们面临的挑战 松散的键入,因此我们必须同时更改这两种类型 测试和实现 同时也不会有普通测试的支架效应 重构。我认为人们实际上可以“加强”这种松散的多态性, 并将代码抽象成一个函数,而不是立即将其删除。但是会 这是个好主意吗?
    2 回复  |  直到 17 年前
        1
  •  7
  •   Steve Jessop    17 年前

    您不能定义某种get_id方法,以便id返回自身,对象返回id,名称执行获取id所需的任何操作吗?然后你就可以把任何你知道是三者之一的东西标准化。同样,如果需要,使用get_name和get_object方法。

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

        2
  •  4
  •   Chuck    17 年前

    几乎在您发现自己打开对象的类的任何时候,都会提示该行为应该是对象本身的一种方法。消息发送 基于接收器的多态性。在这种情况下,它应该类似于:

    def initialize starting_value
      @starting_id = starting_value.id
    end
    

    定义 id 做各种各样的事情 get_id_from_* 方法用来做。非法类型案例将已引发,因为您将得到一个NoMethodError。

    至于如何称呼它,我称之为“OO语言中的过程编程”