視点を変えるだけでスパゲッティコードを解きほぐす
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つは、呼び出し元と呼び出し先を逆にしてみることです。 上記のコードを使用した例を次に示します。
class Quote
...
def add_line_item(line_item)
line_item.add_to_quote(self)
end
end
class Ad < LineItem
...
def add_to_quote(quote)
quote.line_items << self
end
end
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つです。このパターンを使用した後に私が書いたコードは、より明確で自信がある傾向があります。
しかし、そうでない場合でも、このパターンを使用すると、オブジェクト間の関係について別の方法で考えるようになります。 「この機能はひどいので、それを処理するためにこのひどいコードを書かなければならないなんて信じられない」という轍に入ると、それらの問題を解決できる新しい方法を頭に浮かび上がらせます。 コードを別の方法で構造化する方法を考える必要があります それは非常に便利です。
私のお気に入りのパターンの多くと同様に、私は最初に反転方法に出くわしました。 Smalltalkのベストプラクティスパターンで、それ以来、貴重なツールとなっています。
次回、動作が少し異なる類似のオブジェクトを処理するのに苦労するときは、試してみてください。新しいコードがもっと好きなら、それを保持してください。そうしなくても、より良いコードにつながる道を歩むことになります。
-
ターミナルの簡単な微調整で OS X の通知バナーの長さを変更
2 年前に OS X Lion がリリースされたとき、Apple は独自のバナー システムを使用してプッシュ通知を Mac に導入しました。ご存知かもしれませんが、Mac で通知を受け取ると、ディスプレイの右上隅にバナーが表示され、そこに 25 秒間留まり、深淵に消えます。一部の Mac ユーザーは、これらのバナーが長時間表示されていることに不満を持っており、他のユーザーはバナーがすぐに消えてしまうことに不満を持っています. あなたがこれらの Mac ユーザーのいずれかであれば、幸運です。簡単なターミナル コマンドを使用して、これらのバナーが表示される時間を正確に制御する方法があることがわか
-
IE 8 から 11 のソース コード エディターの表示を変更する
Internet Explorer で Web ページのソース コードを表示したことがありますか?インターネット上で表示されるすべての Web ページは、実際には、HTML、CSS、Javascript などのさまざまな言語で記述されたコードにすぎません。これらすべての要素が組み合わさって、表示および操作できる Web ページが作成されます。 デフォルトでは、IE は Web ページのソース コードを別の IE ウィンドウで開きますが、これはほとんどの人にとって問題ありません。開発者またはコーダーである場合は、別のテキスト エディターまたはコード エディターを使用してソース コードを表示する