Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

視点を変えるだけでスパゲッティコードを解きほぐす

ifの巨大な混乱 ステートメントはあなたの顔を見つめ続けます。 すべきような気がします 邪魔をし続けるビジネスロジックを除いて、それを単純化することができます。

たとえば、Quoteを作成する販売プラットフォームがあるとします。 s、多くのLineItem s。ただし、広告の場合は、広告申込情報が重複している見積もりを作成できます。 、ただし、複数のウェブサイトがある場合 、価格を合計して、単一の広告申込情報として表示する必要があります。また、ウェブサイトを購入し、見積もりにすでに5つの広告がある場合は、ウェブサイトで20%の割引を提供する必要があります。

ここからずっと、窓からノートパソコンを投げているのが聞こえます。

あなたはできた たくさんのifを書く これらのルールを処理するステートメント:

class Quote
  attr_accessor :line_items
 
  ... 
 
  def add_line_item(line_item)
    if line_item.kind_of?(Ad)
      self.line_items << line_item
    elsif line_item.kind_of?(Website)
      if @line_items.select {|item| item.kind_of?(Ad) }.length >= 5
        # TODO: Put the fractions of a cent into a bank account
        # I have set up
        line_item.price *= 0.8
      end
      existing_website = self.line_items.detect { |item| item.kind_of?(Website) }
      if existing_website
        existing_website.price += line_item.price
      else
        self.line_items << line_item
      end
    end
  end
end

しかし、それはひどいことに同意できると思います。 どうすればそのようなものを解くことができますか?

メソッドを小さなメソッドの束に分解することもできますが、それはクローゼットにすべてのおもちゃを押し込んで、お母さんが部屋を掃除したと思うようにするようなものです。そして、それらのkind_of? sはまだ私を大いに悩ませます。

しかし、広告申込情報から物事を見始めたらどうなるでしょうか。 引用の代わりに、視点? 質問の代わりに 扱っている広告申込情報の種類を見積もりに追加すると、伝えた それ自体を追加する広告申込情報 見積もりに?

メソッドを逆にします!

コードをリファクタリングする私のお気に入りの方法の1つは、呼び出し元と呼び出し先を逆にしてみることです。 上記のコードを使用した例を次に示します。

app / models / quote.rb
class Quote
  ...
  def add_line_item(line_item)
    line_item.add_to_quote(self)
  end
end
app / models / line_item.rb
class Ad < LineItem
  ...
  def add_to_quote(quote)
    quote.line_items << self
  end 
end
app / models / website.rb
class Website < LineItem
  def add_to_quote(quote)
    if quote.line_items.select {|item| item.kind_of?(Ad) }.length >= 5
      # TODO: Put the fractions of a cent into a bank account
      # I have set up
      self.price *= 0.8
    end
    existing_website = quote.line_items.detect { |item| item.kind_of?(Website) }
    if existing_website
      existing_website.price += self.price
    else
	  quote.line_items << self
    end
  end
end

完璧ではありません。 website.rb まだロットが必要です リファクタリングのヘルプであり、メソッドを逆にするとline_itemsのカプセル化がどのように壊れたかに満足していません。 。

しかし、あなたは複雑さの最初の層を取り除きました。これで、LineItemにコードを配置できます または Quote 、それが最も理にかなっている場所に応じて。 LineItem オブジェクトは、継承とミックスインを使用して、各LineItem間の類似点と相違点を処理できます。 サブクラス。さらに、新しいLineItemを簡単に追加できるようになりました add_line_itemを肥大化させずにサブクラス メソッド。

コードは少しすっきりしていて、はるかに柔軟です。 一般的に、私はそれを勝利と呼びます。

このパターンを使用したくない場合

反転方法と同じくらい便利です つまり、このパターンを使用したくない理由がいくつかあります。

  • カプセル化を破る可能性があります。 Quoteで属性を公開する必要がある場合があります 公開したくないオブジェクト。

  • 結合を増やすことができます。 両方のQuote およびAd 今、お互いについて知る必要があります。そして、どれだけかによって異なります 彼らはお互いについて知る必要があります、それはあなたのコードをもっとすることができます 複雑です。

  • Adの単一責任原則に違反する可能性があります Ad Quoteに自分自身を追加する方法を知る責任があります 。

通常、これらの問題を回避できます。ただし、コードを悪化させるためにリファクタリングしたくないので、これらに注意する必要があります!

なぜそれが私のお気に入りの1つなのか

これらの問題があっても、これは私のお気に入りのリファクタリングの1つです。このパターンを使用した後に私が書いたコードは、より明確で自信がある傾向があります。

しかし、そうでない場合でも、このパターンを使用すると、オブジェクト間の関係について別の方法で考えるようになります。 「この機能はひどいので、それを処理するためにこのひどいコードを書かなければならないなんて信じられない」という轍に入ると、それらの問題を解決できる新しい方法を頭に浮かび上がらせます。 コードを別の方法で構造化する方法を考える必要があります それは非常に便利です。

自分のコードで試してみてください

私のお気に入りのパターンの多くと同様に、私は最初に反転方法に出くわしました。 Smalltalkのベストプラクティスパターンで、それ以来、貴重なツールとなっています。

次回、動作が少し異なる類似のオブジェクトを処理するのに苦労するときは、試してみてください。新しいコードがもっと好きなら、それを保持してください。そうしなくても、より良いコードにつながる道を歩むことになります。


  1. ターミナルの簡単な微調整で OS X の通知バナーの長さを変更

    2 年前に OS X Lion がリリースされたとき、Apple は独自のバナー システムを使用してプッシュ通知を Mac に導入しました。ご存知かもしれませんが、Mac で通知を受け取ると、ディスプレイの右上隅にバナーが表示され、そこに 25 秒間留まり、深淵に消えます。一部の Mac ユーザーは、これらのバナーが長時間表示されていることに不満を持っており、他のユーザーはバナーがすぐに消えてしまうことに不満を持っています. あなたがこれらの Mac ユーザーのいずれかであれば、幸運です。簡単なターミナル コマンドを使用して、これらのバナーが表示される時間を正確に制御する方法があることがわか

  2. IE 8 から 11 のソース コード エディターの表示を変更する

    Internet Explorer で Web ページのソース コードを表示したことがありますか?インターネット上で表示されるすべての Web ページは、実際には、HTML、CSS、Javascript などのさまざまな言語で記述されたコードにすぎません。これらすべての要素が組み合わさって、表示および操作できる Web ページが作成されます。 デフォルトでは、IE は Web ページのソース コードを別の IE ウィンドウで開きますが、これはほとんどの人にとって問題ありません。開発者またはコーダーである場合は、別のテキスト エディターまたはコード エディターを使用してソース コードを表示する