1

車の今後のサービスの必要性についてユーザーを更新するために、車の走行距離とサービス履歴を追跡するプログラムを作成しました。

Car、、、の 3 つのクラスがCarHistoryありCarServiceHistoryEntryます。3 つ目は簡単です。サービスに関連付けられたすべての属性 (日付、走行距離、実行されたサービスなど) を保持します。CarHistoryクラスは次のとおりです。

require_relative 'car_service_history_entry'

class CarHistory
  attr_reader :entries
  def initialize (*entry)
    if entry.size > 1
      @entries = []
    else
      @entries = entry
    end
  end
  def add_service_entry entry
    @entries << entry
  end
  def to_s
    entries_string = ""
    @entries.each {|entry| entries_string << "#{entry.to_s}\n"}
    entries_string
  end
end
  1. initialize、のクラスをentryチェックする必要がありますか?
  2. ではadd_service_entry、ダック タイピング (「プログラミング Ruby」での Andy Thomas の議論のように) を採用して、aCarServiceHistoryEntryを追加できるかどうかをテストしますか? StringセットアップしCarServiceHistoryEntryて単体テストに追加する代わりに、 a を渡すことはできませんか?
  3. a の必要な属性は配列とメソッドだけなので、CarHistoryこのentriesクラスto_sをまとめて破棄してクラスに入れるべきcarでしょうか?
4

3 に答える 3

1

クラスと他のクラスとの関係についてコメントするのは難しいCarHistoryですが、作業を進めていくうちに明らかになると思います。

ifあなたのメソッドのいくつかは単純化できますが、私は を理解していなかったと言わざるを得ませinitialize> 0

def initialize *entry
  @entries = entry # if not specified it will be [] anyway
end

def to_s
  @entries.join "\n"
end

そうです、Ruby はシンプルであるべきです。実行時の型チェックでコードを散らかす必要はありません。コードが単体テストを実行する場合は、勝利を宣言するだけです。無数の明示的な変換は、とにかく型エラーを修正する傾向があります。

いずれにせよ、Ruby は実行時に型をチェックします。型チェックをインタープリターに任せて、機能テストに力を入れることは完全に合理的です。

于 2011-05-26T04:35:15.077 に答える
1

1 と 2 については、Ruby のような緩やかな型付けの言語に移行するときは、「厳密な型付け」に対する固執を手放す必要があります。

  • 入力引数を確認する必要がありますか? 伝統的な答えはイエスでしょう。別の方法は、型がどのように機能するかを文書化して指定する適切な名前と単体テストを用意することです。それが他のタイプで動作する場合は、問題ありません..それは追加のボーナスです. したがって、互換性のない型を渡すと、例外が発生して爆発しますが、ほとんどの場合、これで十分です。試してみて、それがどのように感じられるかを確認してください (考えられる結果: 解放/「後退!」。しかし、公正な試みをしてください)。例外は、ルールが異なる共有ライブラリ用のパブリック API を設計している場合です。悪い入力については、迅速かつ有益に失敗する必要があります。
  • car_history を car にクラブ化することについては、 Car クラスの責任についてお尋ねします。独自の歴史を維持することがその1つである場合、それらをクラブにすることができます. 将来、車の履歴に関連する多くのメソッドが忍び寄っているのを見つけた場合は、この決定を逆にして CarHistory タイプを再度抽出することができます。SingleResponsibilityPrinciple を使用して、情報に基づいた決定を下します。これは単なる OOP です。Ruby はオブジェクトの設計を低下させません。

コード スニペット: コードをより簡潔にすることができます

# just for simplicity, I'm making HistoryEntry a string, it could be a custom type too
class CarServiceHistoryEntry << String
end

class CarHistory
  attr_reader :entries
  def initialize(*history_entries)
    @entries = history_entries
  end

  def add_service_entry(entry)
    @entries << entry
  end
  def to_s
    @entries.join("\n")
  end
end

irb>x = CarHistory.new("May 01 Overhaul", "May 30 minor repairs")
irb>x.add_service_entry("June 12 Cracked windshield")
irb>x.to_s
=> "May 01 Overhaul\nMay 30 minor repairs\nJune 12 Cracked windshield"
于 2011-05-26T04:37:35.860 に答える