17

私はまだ Ruby に非常に慣れていません (つるはしを読み、ほとんどの時間を .NET に費やしていますirb)。Ruby でクラスにパッチを適用できることがわかったので、それがいつ許容されるのか、具体的にはそれが許容されるかどうか疑問に思っていますRuby の基本クラスにパッチを当てます。例: ここで別の Ruby の質問に答えました。ここでは、投稿者が から時間を減算する方法を知りたがっていましたDateTimeDateTimeクラスはこの機能を提供していないように見えるため、可能な解決策としてクラスとクラスにパッチを当てる回答を投稿しましDateTimeFixnum。これは私が提出したコードです:

require 'date'

# A placeholder class for holding a set number of hours.
# Used so we can know when to change the behavior
# of DateTime#-() by recognizing when hours are explicitly passed in.

class Hours
   attr_reader :value

   def initialize(value)
      @value = value
   end
end

# Patch the #-() method to handle subtracting hours
# in addition to what it normally does

class DateTime

   alias old_subtract -

   def -(x) 
      case x
        when Hours; return DateTime.new(year, month, day, hour-x.value, min, sec)
        else;       return self.old_subtract(x)
      end
   end

end

# Add an #hours attribute to Fixnum that returns an Hours object. 
# This is for syntactic sugar, allowing you to write "someDate - 4.hours" for example

class Fixnum
   def hours
      Hours.new(self)
   end
end

クラスにパッチを適用したのは、この例では、DateTime. 具体的には、上記のコードの結果として、次のようなことができます。

five_hours_ago = DateTime.now - 5.hours

これはかなり見やすく、理解しやすいようです。DateTimeただし、の-演算子の機能をいじるのが良い考えかどうかはわかりません。

この状況で考えられる唯一の選択肢は次のとおりです。

1.DateTimeオンザフライで新しいオブジェクトを作成し、呼び出しで新しい時間の値を計算するだけです。new

new_date = DateTime.new(old_date.year, old_date.year, old_date.month, old_date.year.day, old_date.hour - hours_to_subtract, date.min, date.sec)


DateTime2. aと、そこから減算する時間数を受け入れるユーティリティ メソッドを作成します。

基本的に、方法 (1) の単なるラッパーです。

def subtract_hours(date, hours)
  return DateTime.new(date.year, date.month, date.day, date.hour - hours, date.min, date.sec)
end


DateTime3.の既存の動作を変更する代わりに、新しいメソッドを追加します#-()

おそらく、次のような構文を可能にするために、パッチとDateTime#less一緒に機能する新しいメソッドです。Fixnum#hours

date.less(5.hours)

ただし、既に述べたように、パッチを適用するアプローチを採用したのは、より表現力豊かな構文が得られると考えたからです。

私のアプローチに何か問題がありますか、またはこれを行うために3つの選択肢の1つ(または私が考えていない別のもの)を使用する必要がありますか? パッチを適用することが Ruby の問題に対する新しい「ハンマー」になりつつあると感じているので、「Ruby のやり方」で物事を行っているかどうかについてフィードバックを得たいと思います。

4

4 に答える 4

18

私の個人的な答えは、一言で言えば、コアクラスのパッチハンマーはツールボックスの下部にあるはずです。あなたが利用できる他の多くの技術があり、ほとんどすべての場合、それらは十分で、よりクリーンで、より持続可能です。

ただし、実際にはコーディングしている環境によって異なります。個人的なプロジェクトの場合は、心ゆくまでパッチを当ててください。問題は、大規模なプログラマーのグループで長期間にわたって大規模なコードベースで作業しているときに発生し始めます。私が働いている組織では、100KLOCを超えるRubyコードベースと20人ほどの開発者がいますが、モンキーパッチは頭を悩ませる、工数の浪費につながることがわかっているため、かなり厳しく取り締まり始めています。あまりにも頻繁に。現時点では、ソースパッチがまだ組み込まれていないか、組み込まれないサードパーティのコードに一時的にパッチを適用する場合にのみ許容されます。

于 2008-10-27T02:03:39.547 に答える
6

個人的には、基本クラスにメソッドを追加することは容認できますが、既存のメソッドの実装を変更することは容認できないと思います。

于 2008-10-27T01:06:42.407 に答える
5

最も安全な方法は、組み込みのクラスを継承する独自のクラスを定義してから、新しいクラスに新しいものを追加することです。

class MyDateTime < DateTime
  alias...
  def...

しかし、明らかに今では、新しいクラスのオブジェクトを宣言した場合にのみ、新しい動作が得られます。

于 2008-10-27T01:56:37.063 に答える
0

私はそれがこのようだと思います:あなたが他のほとんどのプログラマーがあなたのパッチに同意するだろうと正直に感じるなら、それなら大丈夫です。そうでない場合は、代わりにコードライブラリを実装する必要がありますか?

于 2008-10-27T01:14:26.960 に答える