5

かなり大規模な Ruby アプリケーションでは、特定のオブジェクトが名前と ID などの 2 つの要素によって識別される状況があります。これらの値の型はそれぞれ多少異なる目的を果たしているため、厳密には同じではありません (ID と名前は別の場所に保持されます)。そのため、アプリケーション全体でさまざまな値 (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

私たちのコードベース (イニシャライザだけでなく) の周りにこのコードが急増すると、私が「乱雑なポリモーフィズム」と呼ぶ結果になります。多くの場合は機能しますが、非常に不可解な状況が生じることもあります。

これについて 3 つの質問があります。

  • アンチパターンとしてこれに正式な名前はありますか? 「乱雑なインターフェイス?」、「乱雑なポリモーフィズム?」または、他の何か?
  • 人々はこれがどれほど悪いと思うでしょうか?
  • これをリファクタリングする体系的な方法はありますか? 私たちが作成した多くのテストがこのルーズタイピングを使用しているため、テストと実装の両方を同時に変更する必要があり、通常のテストベースのリファクタリングの足場効果がないという、通常のリファクタリングでの課題です。この緩やかなポリモーフィズムを実際に「強化」し、コードをすぐに切り取るのではなく、関数に抽象化することができると思います。しかし、これは良い考えでしょうか?
4

2 に答える 2

4

オブジェクトのクラスをオンにしている場合は、ほとんどいつでも、その動作がオブジェクト自体のメソッドである必要があるという手がかりになります。メッセージのディスパッチ、受信者に基づいてポリモーフィックです。この場合、次のようになります。

def initialize starting_value
  @starting_id = starting_value.id
end

idさまざまなget_id_from_*メソッドが行っていたすべてのことを行うように定義します。NoMethodError が発生するため、不正な型のケースはすでに発生しています。

これを何と呼ぶか​​というと、私は「オブジェクト指向言語の手続き型プログラミング」と呼んでいます。

于 2009-04-03T00:25:23.697 に答える